Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband: (33 commits)
  IB/ipath: Fix lockdep error upon "ifconfig ibN down"
  IB/ipath: Fix races with ib_resize_cq()
  IB/ipath: Support new PCIE device, QLE7142
  IB/ipath: Set CPU affinity early
  IB/ipath: Fix EEPROM read when driver is compiled with -Os
  IB/ipath: Fix and recover TXE piobuf and PBC parity errors
  IB/ipath: Change HT CRC message to indicate how to resolve problem
  IB/ipath: Clean up module exit code
  IB/ipath: Call mtrr_del with correct arguments
  IB/ipath: Flush RWQEs if access error or invalid error seen
  IB/ipath: Improved support for PowerPC
  IB/ipath: Drop unnecessary "(void *)" casts
  IB/ipath: Support multiple simultaneous devices of different types
  IB/ipath: Fix mismatch in shifts and masks for printing debug info
  IB/ipath: Fix compiler warnings and errors on non-x86_64 systems
  IB/ipath: Print more informative parity error messages
  IB/ipath: Ensure that PD of MR matches PD of QP checking the Rkey
  IB/ipath: RC and UC should validate SLID and DLID
  IB/ipath: Only allow complete writes to flash
  IB/ipath: Count SRQs properly
  ...
diff --git a/CREDITS b/CREDITS
index cc3453a..66e8246 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1620,7 +1620,8 @@
 
 N: Jesper Juhl
 E: jesper.juhl@gmail.com
-D: Various fixes, cleanups and minor features.
+D: Various fixes, cleanups and minor features all over the tree.
+D: Wrote initial version of the hdaps driver (since passed on to others).
 S: Lemnosvej 1, 3.tv
 S: 2300 Copenhagen S.
 S: Denmark
@@ -2477,7 +2478,8 @@
 S: United Kingdom
 
 N: Ian S. Nelson
-E: ian.nelson@echostar.com
+E: nelsonis@earthlink.net
+P: 1024D/00D3D983 3EFD 7B86 B888 D7E2 29B6  9E97 576F 1B97 00D3 D983
 D: Minor mmap and ide hacks
 S: 1370 Atlantis Ave.
 S: Lafayette CO, 80026
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 6d2412e..29c1896 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -532,6 +532,40 @@
 something it would have done anyway.
 
 
+		Chapter 16: Function return values and names
+
+Functions can return values of many different kinds, and one of the
+most common is a value indicating whether the function succeeded or
+failed.  Such a value can be represented as an error-code integer
+(-Exxx = failure, 0 = success) or a "succeeded" boolean (0 = failure,
+non-zero = success).
+
+Mixing up these two sorts of representations is a fertile source of
+difficult-to-find bugs.  If the C language included a strong distinction
+between integers and booleans then the compiler would find these mistakes
+for us... but it doesn't.  To help prevent such bugs, always follow this
+convention:
+
+	If the name of a function is an action or an imperative command,
+	the function should return an error-code integer.  If the name
+	is a predicate, the function should return a "succeeded" boolean.
+
+For example, "add work" is a command, and the add_work() function returns 0
+for success or -EBUSY for failure.  In the same way, "PCI device present" is
+a predicate, and the pci_dev_present() function returns 1 if it succeeds in
+finding a matching device or 0 if it doesn't.
+
+All EXPORTed functions must respect this convention, and so should all
+public functions.  Private (static) functions need not, but it is
+recommended that they do.
+
+Functions whose return value is the actual result of a computation, rather
+than an indication of whether the computation succeeded, are not subject to
+this rule.  Generally they indicate failure by returning some out-of-range
+result.  Typical examples would be functions that return pointers; they use
+NULL or the ERR_PTR mechanism to report failure.
+
+
 
 		Appendix I: References
 
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index f8fe882..6d4b1ef 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -181,27 +181,6 @@
      </sect1>
   </chapter>
 
-  <chapter id="proc">
-     <title>The proc filesystem</title>
- 
-     <sect1><title>sysctl interface</title>
-!Ekernel/sysctl.c
-     </sect1>
-
-     <sect1><title>proc filesystem interface</title>
-!Ifs/proc/base.c
-     </sect1>
-  </chapter>
-
-  <chapter id="debugfs">
-     <title>The debugfs filesystem</title>
- 
-     <sect1><title>debugfs interface</title>
-!Efs/debugfs/inode.c
-!Efs/debugfs/file.c
-     </sect1>
-  </chapter>
-
   <chapter id="vfs">
      <title>The Linux VFS</title>
      <sect1><title>The Filesystem types</title>
@@ -234,6 +213,50 @@
      </sect1>
   </chapter>
 
+  <chapter id="proc">
+     <title>The proc filesystem</title>
+ 
+     <sect1><title>sysctl interface</title>
+!Ekernel/sysctl.c
+     </sect1>
+
+     <sect1><title>proc filesystem interface</title>
+!Ifs/proc/base.c
+     </sect1>
+  </chapter>
+
+  <chapter id="sysfs">
+     <title>The Filesystem for Exporting Kernel Objects</title>
+!Efs/sysfs/file.c
+!Efs/sysfs/symlink.c
+!Efs/sysfs/bin.c
+  </chapter>
+
+  <chapter id="debugfs">
+     <title>The debugfs filesystem</title>
+ 
+     <sect1><title>debugfs interface</title>
+!Efs/debugfs/inode.c
+!Efs/debugfs/file.c
+     </sect1>
+  </chapter>
+
+  <chapter id="relayfs">
+     <title>relay interface support</title>
+
+     <para>
+	Relay interface support
+	is designed to provide an efficient mechanism for tools and
+	facilities to relay large amounts of data from kernel space to
+	user space.
+     </para>
+
+     <sect1><title>relay interface</title>
+!Ekernel/relay.c
+!Ikernel/relay.c
+     </sect1>
+  </chapter>
+
   <chapter id="netcore">
      <title>Linux Networking</title>
      <sect1><title>Networking Base Types</title>
@@ -349,13 +372,6 @@
      </sect1>
   </chapter>
 
-  <chapter id="sysfs">
-     <title>The Filesystem for Exporting Kernel Objects</title>
-!Efs/sysfs/file.c
-!Efs/sysfs/symlink.c
-!Efs/sysfs/bin.c
-  </chapter>
-
   <chapter id="security">
      <title>Security Framework</title>
 !Esecurity/security.c
@@ -386,6 +402,7 @@
 -->
 !Edrivers/base/driver.c
 !Edrivers/base/core.c
+!Edrivers/base/class.c
 !Edrivers/base/firmware_class.c
 !Edrivers/base/transport_class.c
 !Edrivers/base/dmapool.c
@@ -437,6 +454,11 @@
 !Eblock/ll_rw_blk.c
   </chapter>
 
+  <chapter id="chrdev">
+	<title>Char devices</title>
+!Efs/char_dev.c
+  </chapter>
+
   <chapter id="miscdev">
      <title>Miscellaneous Devices</title>
 !Edrivers/char/misc.c
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index 320af25..3608472 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -43,59 +43,52 @@
 
     <para>A Universal Serial Bus (USB) is used to connect a host,
     such as a PC or workstation, to a number of peripheral
-    devices.  USB uses a tree structure, with the host at the
+    devices.  USB uses a tree structure, with the host as the
     root (the system's master), hubs as interior nodes, and
-    peripheral devices as leaves (and slaves).
+    peripherals as leaves (and slaves).
     Modern PCs support several such trees of USB devices, usually
     one USB 2.0 tree (480 Mbit/sec each) with
     a few USB 1.1 trees (12 Mbit/sec each) that are used when you
     connect a USB 1.1 device directly to the machine's "root hub".
     </para>
 
-    <para>That master/slave asymmetry was designed in part for
-    ease of use.  It is not physically possible to assemble
-    (legal) USB cables incorrectly:  all upstream "to-the-host"
-    connectors are the rectangular type, matching the sockets on
-    root hubs, and the downstream type are the squarish type
-    (or they are built in to the peripheral).
-    Software doesn't need to deal with distributed autoconfiguration
-    since the pre-designated master node manages all that.
-    At the electrical level, bus protocol overhead is reduced by
-    eliminating arbitration and moving scheduling into host software.
+    <para>That master/slave asymmetry was designed-in for a number of
+    reasons, one being ease of use.  It is not physically possible to
+    assemble (legal) USB cables incorrectly:  all upstream "to the host"
+    connectors are the rectangular type (matching the sockets on
+    root hubs), and all downstream connectors are the squarish type
+    (or they are built into the peripheral).
+    Also, the host software doesn't need to deal with distributed
+    auto-configuration since the pre-designated master node manages all that.
+    And finally, at the electrical level, bus protocol overhead is reduced by
+    eliminating arbitration and moving scheduling into the host software.
     </para>
 
-    <para>USB 1.0 was announced in January 1996, and was revised
+    <para>USB 1.0 was announced in January 1996 and was revised
     as USB 1.1 (with improvements in hub specification and
     support for interrupt-out transfers) in September 1998.
-    USB 2.0 was released in April 2000, including high speed
-    transfers and transaction translating hubs (used for USB 1.1
+    USB 2.0 was released in April 2000, adding high-speed
+    transfers and transaction-translating hubs (used for USB 1.1
     and 1.0 backward compatibility).
     </para>
 
-    <para>USB support was added to Linux early in the 2.2 kernel series
-    shortly before the 2.3 development forked off.  Updates
-    from 2.3 were regularly folded back into 2.2 releases, bringing
-    new features such as <filename>/sbin/hotplug</filename> support,
-    more drivers, and more robustness.
-    The 2.5 kernel series continued such improvements, and also
-    worked on USB 2.0 support,
-    higher performance,
-    better consistency between host controller drivers,
-    API simplification (to make bugs less likely),
-    and providing internal "kerneldoc" documentation.
+    <para>Kernel developers added USB support to Linux early in the 2.2 kernel
+    series, shortly before 2.3 development forked.  Updates from 2.3 were
+    regularly folded back into 2.2 releases, which improved reliability and
+    brought <filename>/sbin/hotplug</filename> support as well more drivers.
+    Such improvements were continued in the 2.5 kernel series, where they added
+    USB 2.0 support, improved performance, and made the host controller drivers
+    (HCDs) more consistent.  They also simplified the API (to make bugs less
+    likely) and added internal "kerneldoc" documentation.
     </para>
 
     <para>Linux can run inside USB devices as well as on
     the hosts that control the devices.
-    Because the Linux 2.x USB support evolved to support mass market
-    platforms such as Apple Macintosh or PC-compatible systems,
-    it didn't address design concerns for those types of USB systems.
-    So it can't be used inside mass-market PDAs, or other peripherals.
-    USB device drivers running inside those Linux peripherals
+    But USB device drivers running inside those peripherals
     don't do the same things as the ones running inside hosts,
-    and so they've been given a different name:
-    they're called <emphasis>gadget drivers</emphasis>.
-    This document does not present gadget drivers.
+    so they've been given a different name:
+    <emphasis>gadget drivers</emphasis>.
+    This document does not cover gadget drivers.
     </para>
 
     </chapter>
@@ -103,17 +96,14 @@
 <chapter id="host">
     <title>USB Host-Side API Model</title>
 
-    <para>Within the kernel,
-    host-side drivers for USB devices talk to the "usbcore" APIs.
-    There are two types of public "usbcore" APIs, targetted at two different
-    layers of USB driver.  Those are
-    <emphasis>general purpose</emphasis> drivers, exposed through
-    driver frameworks such as block, character, or network devices;
-    and drivers that are <emphasis>part of the core</emphasis>,
-    which are involved in managing a USB bus.
-    Such core drivers include the <emphasis>hub</emphasis> driver,
-    which manages trees of USB devices, and several different kinds
-    of <emphasis>host controller driver (HCD)</emphasis>,
+    <para>Host-side drivers for USB devices talk to the "usbcore" APIs.
+    There are two.  One is intended for
+    <emphasis>general-purpose</emphasis> drivers (exposed through
+    driver frameworks), and the other is for drivers that are
+    <emphasis>part of the core</emphasis>.
+    Such core drivers include the <emphasis>hub</emphasis> driver
+    (which manages trees of USB devices) and several different kinds
+    of <emphasis>host controller drivers</emphasis>,
     which control individual busses.
     </para>
 
@@ -122,21 +112,21 @@
      
     <itemizedlist>
 
-	<listitem><para>USB supports four kinds of data transfer
-	(control, bulk, interrupt, and isochronous).  Two transfer
-	types use bandwidth as it's available (control and bulk),
-	while the other two types of transfer (interrupt and isochronous)
+	<listitem><para>USB supports four kinds of data transfers
+	(control, bulk, interrupt, and isochronous).  Two of them (control
+	and bulk) use bandwidth as it's available,
+	while the other two (interrupt and isochronous)
 	are scheduled to provide guaranteed bandwidth.
 	</para></listitem>
 
 	<listitem><para>The device description model includes one or more
 	"configurations" per device, only one of which is active at a time.
-	Devices that are capable of high speed operation must also support
-	full speed configurations, along with a way to ask about the
-	"other speed" configurations that might be used.
+	Devices that are capable of high-speed operation must also support
+	full-speed configurations, along with a way to ask about the
+	"other speed" configurations which might be used.
 	</para></listitem>
 
-	<listitem><para>Configurations have one or more "interface", each
+	<listitem><para>Configurations have one or more "interfaces", each
 	of which may have "alternate settings".  Interfaces may be
 	standardized by USB "Class" specifications, or may be specific to
 	a vendor or device.</para>
@@ -162,7 +152,7 @@
 	</para></listitem>
 
 	<listitem><para>The Linux USB API supports synchronous calls for
-	control and bulk messaging.
+	control and bulk messages.
 	It also supports asynchnous calls for all kinds of data transfer,
 	using request structures called "URBs" (USB Request Blocks).
 	</para></listitem>
@@ -463,14 +453,25 @@
 	    file in your Linux kernel sources.
 	    </para>
 
-	    <para>Otherwise the main use for this file from programs
-	    is to poll() it to get notifications of usb devices
-	    as they're plugged or unplugged.
-	    To see what changed, you'd need to read the file and
-	    compare "before" and "after" contents, scan the filesystem,
-	    or see its hotplug event.
-	    </para>
+	    <para>This file, in combination with the poll() system call, can
+	    also be used to detect when devices are added or removed:
+<programlisting>int fd;
+struct pollfd pfd;
 
+fd = open("/proc/bus/usb/devices", O_RDONLY);
+pfd = { fd, POLLIN, 0 };
+for (;;) {
+	/* The first time through, this call will return immediately. */
+	poll(&amp;pfd, 1, -1);
+
+	/* To see what's changed, compare the file's previous and current
+	   contents or scan the filesystem.  (Scanning is more precise.) */
+}</programlisting>
+	    Note that this behavior is intended to be used for informational
+	    and debug purposes.  It would be more appropriate to use programs
+	    such as udev or HAL to initialize a device or start a user-mode
+	    helper program, for instance.
+	    </para>
 	</sect1>
 
 	<sect1>
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index a10bfb6..a6cb6ff 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -61,3 +61,6 @@
     Documentation/kernel-parameters.txt.
 
 18: All new module parameters are documented with MODULE_PARM_DESC()
+
+19: All new userspace interfaces are documented in Documentation/ABI/.
+    See Documentation/ABI/README for more information.
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index 6bd30fd..58bead0 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -59,11 +59,11 @@
 		are the same person/entity. If not, the name of
 		the person/entity authorizing use of GPL should be
 		listed in case it's necessary to verify the will of
-		the copright owner.
+		the copyright owner.
 
 Interfaces:	If your driver uses existing interfaces and behaves like
 		other drivers in the same class it will be much more likely
-		to be accepted than if it invents gratuitous new ones. 
+		to be accepted than if it invents gratuitous new ones.
 		If you need to implement a common API over Linux and NT
 		drivers do it in userspace.
 
@@ -88,7 +88,7 @@
 		it will go in the bitbucket.
 
 Control:	In general if there is active maintainance of a driver by
-		the author then patches will be redirected to them unless 
+		the author then patches will be redirected to them unless
 		they are totally obvious and without need of checking.
 		If you want to be the contact and update point for the
 		driver it is a good idea to state this in the comments,
@@ -100,7 +100,7 @@
 Vendor:		Being the hardware vendor and maintaining the driver is
 		often a good thing. If there is a stable working driver from
 		other people already in the tree don't expect 'we are the
-		vendor' to get your driver chosen. Ideally work with the 
+		vendor' to get your driver chosen. Ideally work with the
 		existing driver author to build a single perfect driver.
 
 Author:		It doesn't matter if a large Linux company wrote the driver,
@@ -116,17 +116,13 @@
 	ftp.??.kernel.org:/pub/linux/kernel/...
 	?? == your country code, such as "us", "uk", "fr", etc.
 
-Linux kernel mailing list:		
+Linux kernel mailing list:
 	linux-kernel@vger.kernel.org
 	[mail majordomo@vger.kernel.org to subscribe]
 
 Linux Device Drivers, Third Edition (covers 2.6.10):
 	http://lwn.net/Kernel/LDD3/  (free version)
 
-Kernel traffic:
-	Weekly summary of kernel list activity (much easier to read)
-	http://www.kerneltraffic.org/kernel-traffic/
-
 LWN.net:
 	Weekly summary of kernel development activity - http://lwn.net/
 	2.6 API changes:
@@ -145,11 +141,8 @@
 Linux USB project:
 	http://www.linux-usb.org/
 
-How to NOT write kernel driver by arjanv@redhat.com
-	http://people.redhat.com/arjanv/olspaper.pdf
+How to NOT write kernel driver by Arjan van de Ven:
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
 
 Kernel Janitor:
 	http://janitor.kernelnewbies.org/
-
---
-Last updated on 17 Nov 2005.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index d42ab4c..302d148 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -173,15 +173,15 @@
 trivial@kernel.org managed by Adrian Bunk; which collects "trivial"
 patches. Trivial patches must qualify for one of the following rules:
  Spelling fixes in documentation
- Spelling fixes which could break grep(1).
+ Spelling fixes which could break grep(1)
  Warning fixes (cluttering with useless warnings is bad)
  Compilation fixes (only if they are actually correct)
  Runtime fixes (only if they actually fix things)
- Removing use of deprecated functions/macros (eg. check_region).
+ Removing use of deprecated functions/macros (eg. check_region)
  Contact detail and documentation fixes
  Non-portable code replaced by portable code (even in arch-specific,
  since people copy, as long as it's trivial)
- Any fix by the author/maintainer of the file. (ie. patch monkey
+ Any fix by the author/maintainer of the file (ie. patch monkey
  in re-transmission mode)
 URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
 
@@ -209,6 +209,19 @@
 you to re-send them using MIME.
 
 
+WARNING: Some mailers like Mozilla send your messages with
+---- message header ----
+Content-Type: text/plain; charset=us-ascii; format=flowed
+---- message header ----
+The problem is that "format=flowed" makes some of the mailers
+on receiving side to replace TABs with spaces and do similar
+changes. Thus the patches from you can look corrupted.
+
+To fix this just make your mozilla defaults/pref/mailnews.js file to look like:
+pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
+pref("mailnews.display.disable_format_flowed_support", true);
+
+
 
 7) E-mail size.
 
@@ -245,13 +258,13 @@
 It is quite common for Linus to "drop" your patch without comment.
 That's the nature of the system.  If he drops your patch, it could be
 due to
-* Your patch did not apply cleanly to the latest kernel version
+* Your patch did not apply cleanly to the latest kernel version.
 * Your patch was not sufficiently discussed on linux-kernel.
-* A style issue (see section 2),
-* An e-mail formatting issue (re-read this section)
-* A technical problem with your change
-* He gets tons of e-mail, and yours got lost in the shuffle
-* You are being annoying (See Figure 1)
+* A style issue (see section 2).
+* An e-mail formatting issue (re-read this section).
+* A technical problem with your change.
+* He gets tons of e-mail, and yours got lost in the shuffle.
+* You are being annoying.
 
 When in doubt, solicit comments on linux-kernel mailing list.
 
@@ -476,10 +489,10 @@
 Andrew Morton, "The perfect patch" (tpp).
   <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
 
-Jeff Garzik, "Linux kernel patch submission format."
+Jeff Garzik, "Linux kernel patch submission format".
   <http://linux.yyz.us/patch-format.html>
 
-Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer".
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
   <http://www.kroah.com/log/2005/03/31/>
   <http://www.kroah.com/log/2005/07/08/>
   <http://www.kroah.com/log/2005/10/19/>
@@ -488,9 +501,9 @@
 NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
   <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
 
-Kernel Documentation/CodingStyle
+Kernel Documentation/CodingStyle:
   <http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
 
-Linus Torvald's mail on the canonical patch format:
+Linus Torvalds's mail on the canonical patch format:
   <http://lkml.org/lkml/2005/4/7/183>
 --
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index 76b4429..842f0d1 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -217,11 +217,11 @@
 to represent the cpuset hierarchy provides for a familiar permission
 and name space for cpusets, with a minimum of additional kernel code.
 
-The cpus file in the root (top_cpuset) cpuset is read-only.
-It automatically tracks the value of cpu_online_map, using a CPU
-hotplug notifier.  If and when memory nodes can be hotplugged,
-we expect to make the mems file in the root cpuset read-only
-as well, and have it track the value of node_online_map.
+The cpus and mems files in the root (top_cpuset) cpuset are
+read-only.  The cpus file automatically tracks the value of
+cpu_online_map using a CPU hotplug notifier, and the mems file
+automatically tracks the value of node_online_map using the
+cpuset_track_online_nodes() hook.
 
 
 1.4 What are exclusive cpusets ?
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 66c725f..addc67b 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -2543,6 +2543,9 @@
 		 64 = /dev/usb/rio500	Diamond Rio 500
 		 65 = /dev/usb/usblcd	USBLCD Interface (info@usblcd.de)
 		 66 = /dev/usb/cpad0	Synaptics cPad (mouse/LCD)
+		 67 = /dev/usb/adutux0	1st Ontrak ADU device
+		    ...
+		 76 = /dev/usb/adutux10	10th Ontrak ADU device
 		 96 = /dev/usb/hiddev0	1st USB HID device
 		    ...
 		111 = /dev/usb/hiddev15	16th USB HID device
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 7db71d6..7240ee7 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -39,6 +39,8 @@
   2.9	Appletalk
   2.10	IPX
   2.11	/proc/sys/fs/mqueue - POSIX message queues filesystem
+  2.12	/proc/<pid>/oom_adj - Adjust the oom-killer score
+  2.13	/proc/<pid>/oom_score - Display current oom-killer score
 
 ------------------------------------------------------------------------------
 Preface
@@ -1962,6 +1964,22 @@
 maximum  message size value (it is every  message queue's attribute set during
 its creation).
 
+2.12 /proc/<pid>/oom_adj - Adjust the oom-killer score
+------------------------------------------------------
+
+This file can be used to adjust the score used to select which processes
+should be killed in an  out-of-memory  situation.  Giving it a high score will
+increase the likelihood of this process being killed by the oom-killer.  Valid
+values are in the range -16 to +15, plus the special value -17, which disables
+oom-killing altogether for this process.
+
+2.13 /proc/<pid>/oom_score - Display current oom-killer score
+-------------------------------------------------------------
+
+------------------------------------------------------------------------------
+This file can be used to check the current score used by the oom-killer is for
+any given <pid>. Use it together with /proc/<pid>/oom_adj to tune which
+process should be killed in an out-of-memory situation.
 
 ------------------------------------------------------------------------------
 Summary
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 9555be1..e783fd6 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -13,12 +13,25 @@
                        from Super I/O config space (8 I/O ports)
     Datasheet: Publicly available at the ITE website
                http://www.ite.com.tw/
+  * IT8716F
+    Prefix: 'it8716'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/product_info/file/pc/IT8716F_V0.3.ZIP
+  * IT8718F
+    Prefix: 'it8718'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/product_info/file/pc/IT8718F_V0.2.zip
+               http://www.ite.com.tw/product_info/file/pc/IT8718F_V0%203_(for%20C%20version).zip
   * SiS950   [clone of IT8705F]
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: No longer be available
 
-Author: Christophe Gauthron <chrisg@0-in.com>
+Authors:
+    Christophe Gauthron <chrisg@0-in.com>
+    Jean Delvare <khali@linux-fr.org>
 
 
 Module Parameters
@@ -43,26 +56,46 @@
 Description
 -----------
 
-This driver implements support for the IT8705F, IT8712F and SiS950 chips.
-
-This driver also supports IT8712F, which adds SMBus access, and a VID
-input, used to report the Vcore voltage of the Pentium processor.
-The IT8712F additionally features VID inputs.
+This driver implements support for the IT8705F, IT8712F, IT8716F,
+IT8718F and SiS950 chips.
 
 These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
 joysticks and other miscellaneous stuff. For hardware monitoring, they
 include an 'environment controller' with 3 temperature sensors, 3 fan
 rotation speed sensors, 8 voltage sensors, and associated alarms.
 
+The IT8712F and IT8716F additionally feature VID inputs, used to report
+the Vcore voltage of the processor. The early IT8712F have 5 VID pins,
+the IT8716F and late IT8712F have 6. They are shared with other functions
+though, so the functionality may not be available on a given system.
+The driver dumbly assume it is there.
+
+The IT8718F also features VID inputs (up to 8 pins) but the value is
+stored in the Super-I/O configuration space. Due to technical limitations,
+this value can currently only be read once at initialization time, so
+the driver won't notice and report changes in the VID value. The two
+upper VID bits share their pins with voltage inputs (in5 and in6) so you
+can't have both on a given board.
+
+The IT8716F, IT8718F and later IT8712F revisions have support for
+2 additional fans. They are not yet supported by the driver.
+
+The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
+16-bit tachometer counters for fans 1 to 3. This is better (no more fan
+clock divider mess) but not compatible with the older chips and
+revisions. For now, the driver only uses the 16-bit mode on the
+IT8716F and IT8718F.
+
 Temperatures are measured in degrees Celsius. An alarm is triggered once
 when the Overtemperature Shutdown limit is crossed.
 
 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
-readings can be divided by a programmable divider (1, 2, 4 or 8) to give the
-readings more range or accuracy. Not all RPM values can accurately be
-represented, so some rounding is done. With a divider of 2, the lowest
-representable value is around 2600 RPM.
+triggered if the rotation speed has dropped below a programmable limit. When
+16-bit tachometer counters aren't used, fan readings can be divided by
+a programmable divider (1, 2, 4 or 8) to give the readings more range or
+accuracy. With a divider of 2, the lowest representable value is around
+2600 RPM. Not all RPM values can accurately be represented, so some rounding
+is done.
 
 Voltage sensors (also known as IN sensors) report their values in volts. An
 alarm is triggered if the voltage has crossed a programmable minimum or
@@ -71,9 +104,9 @@
 inputs can measure voltages between 0 and 4.08 volts, with a resolution of
 0.016 volt. The battery voltage in8 does not have limit registers.
 
-The VID lines (IT8712F only) encode the core voltage value: the voltage
-level your processor should work with. This is hardcoded by the mainboard
-and/or processor itself. It is a value in volts.
+The VID lines (IT8712F/IT8716F/IT8718F) encode the core voltage value:
+the voltage level your processor should work with. This is hardcoded by
+the mainboard and/or processor itself. It is a value in volts.
 
 If an alarm triggers, it will remain triggered until the hardware register
 is read at least once. This means that the cause for the alarm may already
diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp
new file mode 100644
index 0000000..bab445a
--- /dev/null
+++ b/Documentation/hwmon/k8temp
@@ -0,0 +1,52 @@
+Kernel driver k8temp
+====================
+
+Supported chips:
+  * AMD K8 CPU
+    Prefix: 'k8temp'
+    Addresses scanned: PCI space
+    Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
+
+Author: Rudolf Marek
+Contact: Rudolf Marek <r.marek@sh.cvut.cz>
+
+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).
+
+There can be up to four temperature sensors inside single CPU. The driver
+will auto-detect the sensors and will display only temperatures from
+implemented sensors.
+
+Mapping of /sys files is as follows:
+
+temp1_input - temperature of Core 0 and "place" 0
+temp2_input - temperature of Core 0 and "place" 1
+temp3_input - temperature of Core 1 and "place" 0
+temp4_input - temperature of Core 1 and "place" 1
+
+Temperatures are measured in degrees Celsius and measurement resolution is
+1 degree C. It is expected that future CPU will have better resolution. The
+temperature is updated once a second. Valid temperatures are from -49 to
+206 degrees C.
+
+Temperature known as TCaseMax was specified for processors up to revision E.
+This temperature is defined as temperature between heat-spreader and CPU
+case, so the internal CPU temperature supplied by this driver can be higher.
+There is no easy way how to measure the temperature which will correlate
+with TCaseMax temperature.
+
+For newer revisions of CPU (rev F, socket AM2) there is a mathematically
+computed temperature called TControl, which must be lower than TControlMax.
+
+The relationship is following:
+
+temp1_input - TjOffset*2 < TControlMax,
+
+TjOffset is not yet exported by the driver, TControlMax is usually
+70 degrees C. The rule of the thumb -> CPU temperature should not cross
+60 degrees C too much.
diff --git a/Documentation/hwmon/vt1211 b/Documentation/hwmon/vt1211
new file mode 100644
index 0000000..77fa633
--- /dev/null
+++ b/Documentation/hwmon/vt1211
@@ -0,0 +1,206 @@
+Kernel driver vt1211
+====================
+
+Supported chips:
+  * VIA VT1211
+    Prefix: 'vt1211'
+    Addresses scanned: none, address read from Super-I/O config space
+    Datasheet: Provided by VIA upon request and under NDA
+
+Authors: Juerg Haefliger <juergh@gmail.com>
+
+This driver is based on the driver for kernel 2.4 by Mark D. Studebaker and
+its port to kernel 2.6 by Lars Ekman.
+
+Thanks to Joseph Chan and Fiona Gatt from VIA for providing documentation and
+technical support.
+
+
+Module Parameters
+-----------------
+
+* uch_config: int	Override the BIOS default universal channel (UCH)
+			configuration for channels 1-5.
+			Legal values are in the range of 0-31. Bit 0 maps to
+			UCH1, bit 1 maps to UCH2 and so on. Setting a bit to 1
+			enables the thermal input of that particular UCH and
+			setting a bit to 0 enables the voltage input.
+
+* int_mode: int		Override the BIOS default temperature interrupt mode.
+			The only possible value is 0 which forces interrupt
+			mode 0. In this mode, any pending interrupt is cleared
+			when the status register is read but is regenerated as
+			long as the temperature stays above the hysteresis
+			limit.
+
+Be aware that overriding BIOS defaults might cause some unwanted side effects!
+
+
+Description
+-----------
+
+The VIA VT1211 Super-I/O chip includes complete hardware monitoring
+capabilities. It monitors 2 dedicated temperature sensor inputs (temp1 and
+temp2), 1 dedicated voltage (in5) and 2 fans. Additionally, the chip
+implements 5 universal input channels (UCH1-5) that can be individually
+programmed to either monitor a voltage or a temperature.
+
+This chip also provides manual and automatic control of fan speeds (according
+to the datasheet). The driver only supports automatic control since the manual
+mode doesn't seem to work as advertised in the datasheet. In fact I couldn't
+get manual mode to work at all! Be aware that automatic mode hasn't been
+tested very well (due to the fact that my EPIA M10000 doesn't have the fans
+connected to the PWM outputs of the VT1211 :-().
+
+The following table shows the relationship between the vt1211 inputs and the
+sysfs nodes.
+
+Sensor          Voltage Mode   Temp Mode   Default Use (from the datasheet)
+------          ------------   ---------   --------------------------------
+Reading 1                      temp1       Intel thermal diode
+Reading 3                      temp2       Internal thermal diode
+UCH1/Reading2   in0            temp3       NTC type thermistor
+UCH2            in1            temp4       +2.5V
+UCH3            in2            temp5       VccP (processor core)
+UCH4            in3            temp6       +5V
+UCH5            in4            temp7       +12V
++3.3V           in5                        Internal VCC (+3.3V)
+
+
+Voltage Monitoring
+------------------
+
+Voltages are sampled by an 8-bit ADC with a LSB of ~10mV. The supported input
+range is thus from 0 to 2.60V. Voltage values outside of this range need
+external scaling resistors. This external scaling needs to be compensated for
+via compute lines in sensors.conf, like:
+
+compute inx @*(1+R1/R2), @/(1+R1/R2)
+
+The board level scaling resistors according to VIA's recommendation are as
+follows. And this is of course totally dependent on the actual board
+implementation :-) You will have to find documentation for your own
+motherboard and edit sensors.conf accordingly.
+
+                                      Expected
+Voltage       R1     R2     Divider   Raw Value
+-----------------------------------------------
++2.5V         2K     10K    1.2       2083 mV
+VccP          ---    ---    1.0       1400 mV (1)
++5V           14K    10K    2.4       2083 mV
++12V          47K    10K    5.7       2105 mV
++3.3V (int)   2K     3.4K   1.588     3300 mV (2)
++3.3V (ext)   6.8K   10K    1.68      1964 mV
+
+(1) Depending on the CPU (1.4V is for a VIA C3 Nehemiah).
+(2) R1 and R2 for 3.3V (int) are internal to the VT1211 chip and the driver
+    performs the scaling and returns the properly scaled voltage value.
+
+Each measured voltage has an associated low and high limit which triggers an
+alarm when crossed.
+
+
+Temperature Monitoring
+----------------------
+
+Temperatures are reported in millidegree Celsius. Each measured temperature
+has a high limit which triggers an alarm if crossed. There is an associated
+hysteresis value with each temperature below which the temperature has to drop
+before the alarm is cleared (this is only true for interrupt mode 0). The
+interrupt mode can be forced to 0 in case the BIOS doesn't do it
+automatically. See the 'Module Parameters' section for details.
+
+All temperature channels except temp2 are external. Temp2 is the VT1211
+internal thermal diode and the driver does all the scaling for temp2 and
+returns the temperature in millidegree Celsius. For the external channels
+temp1 and temp3-temp7, scaling depends on the board implementation and needs
+to be performed in userspace via sensors.conf.
+
+Temp1 is an Intel-type thermal diode which requires the following formula to
+convert between sysfs readings and real temperatures:
+
+compute temp1 (@-Offset)/Gain, (@*Gain)+Offset
+
+According to the VIA VT1211 BIOS porting guide, the following gain and offset
+values should be used:
+
+Diode Type      Offset   Gain
+----------      ------   ----
+Intel CPU       88.638   0.9528
+                65.000   0.9686   *)
+VIA C3 Ezra     83.869   0.9528
+VIA C3 Ezra-T   73.869   0.9528
+
+*) This is the formula from the lm_sensors 2.10.0 sensors.conf file. I don't
+know where it comes from or how it was derived, it's just listed here for
+completeness.
+
+Temp3-temp7 support NTC thermistors. For these channels, the driver returns
+the voltages as seen at the individual pins of UCH1-UCH5. The voltage at the
+pin (Vpin) is formed by a voltage divider made of the thermistor (Rth) and a
+scaling resistor (Rs):
+
+Vpin = 2200 * Rth / (Rs + Rth)   (2200 is the ADC max limit of 2200 mV)
+
+The equation for the thermistor is as follows (google it if you want to know
+more about it):
+
+Rth = Ro * exp(B * (1 / T - 1 / To))   (To is 298.15K (25C) and Ro is the
+                                        nominal resistance at 25C)
+
+Mingling the above two equations and assuming Rs = Ro and B = 3435 yields the
+following formula for sensors.conf:
+
+compute tempx 1 / (1 / 298.15 - (` (2200 / @ - 1)) / 3435) - 273.15,
+              2200 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @))))
+
+
+Fan Speed Control
+-----------------
+
+The VT1211 provides 2 programmable PWM outputs to control the speeds of 2
+fans. Writing a 2 to any of the two pwm[1-2]_enable sysfs nodes will put the
+PWM controller in automatic mode. There is only a single controller that
+controls both PWM outputs but each PWM output can be individually enabled and
+disabled.
+
+Each PWM has 4 associated distinct output duty-cycles: full, high, low and
+off. Full and off are internally hard-wired to 255 (100%) and 0 (0%),
+respectively. High and low can be programmed via
+pwm[1-2]_auto_point[2-3]_pwm. Each PWM output can be associated with a
+different thermal input but - and here's the weird part - only one set of
+thermal thresholds exist that controls both PWMs output duty-cycles. The
+thermal thresholds are accessible via pwm[1-2]_auto_point[1-4]_temp. Note
+that even though there are 2 sets of 4 auto points each, they map to the same
+registers in the VT1211 and programming one set is sufficient (actually only
+the first set pwm1_auto_point[1-4]_temp is writable, the second set is
+read-only).
+
+PWM Auto Point             PWM Output Duty-Cycle
+------------------------------------------------
+pwm[1-2]_auto_point4_pwm   full speed duty-cycle (hard-wired to 255)
+pwm[1-2]_auto_point3_pwm   high speed duty-cycle
+pwm[1-2]_auto_point2_pwm   low speed duty-cycle
+pwm[1-2]_auto_point1_pwm   off duty-cycle (hard-wired to 0)
+
+Temp Auto Point             Thermal Threshold
+---------------------------------------------
+pwm[1-2]_auto_point4_temp   full speed temp
+pwm[1-2]_auto_point3_temp   high speed temp
+pwm[1-2]_auto_point2_temp   low speed temp
+pwm[1-2]_auto_point1_temp   off temp
+
+Long story short, the controller implements the following algorithm to set the
+PWM output duty-cycle based on the input temperature:
+
+Thermal Threshold             Output Duty-Cycle
+                    (Rising Temp)           (Falling Temp)
+----------------------------------------------------------
+                    full speed duty-cycle   full speed duty-cycle
+full speed temp
+                    high speed duty-cycle   full speed duty-cycle
+high speed temp
+                    low speed duty-cycle    high speed duty-cycle
+low speed temp
+                    off duty-cycle          low speed duty-cycle
+off temp
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
new file mode 100644
index 0000000..fae3b78
--- /dev/null
+++ b/Documentation/hwmon/w83627ehf
@@ -0,0 +1,85 @@
+Kernel driver w83627ehf
+=======================
+
+Supported chips:
+  * Winbond W83627EHF/EHG (ISA access ONLY)
+    Prefix: 'w83627ehf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf
+
+Authors:
+        Jean Delvare <khali@linux-fr.org>
+        Yuan Mu (Winbond)
+        Rudolf Marek <r.marek@sh.cvut.cz>
+
+Description
+-----------
+
+This driver implements support for the Winbond W83627EHF and W83627EHG
+super I/O chips. We will refer to them collectively as Winbond chips.
+
+The chips implement three temperature sensors, five fan rotation
+speed sensors, ten analog voltage sensors, alarms with beep warnings (control
+unimplemented), and some automatic fan regulation strategies (plus manual
+fan control mode).
+
+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.
+
+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
+readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
+128) to give the readings more range or accuracy. The driver sets the most
+suitable fan divisor itself. Some fans might not be present because they
+share pins with other functions.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+The driver supports automatic fan control mode known as Thermal Cruise.
+In this mode, the chip attempts to keep the measured temperature in a
+predefined temperature range. If the temperature goes out of range, fan
+is driven slower/faster to reach the predefined range again.
+
+The mode works for fan1-fan4. Mapping of temperatures to pwm outputs is as
+follows:
+
+temp1 -> pwm1
+temp2 -> pwm2
+temp3 -> pwm3
+prog  -> pwm4 (the programmable setting is not supported by the driver)
+
+/sys files
+----------
+
+pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
+	   0 (stop) to 255 (full)
+
+pwm[1-4]_enable - this file controls mode of fan/temperature control:
+	* 1 Manual Mode, write to pwm file any value 0-255 (full speed)
+	* 2 Thermal Cruise
+
+Thermal Cruise mode
+-------------------
+
+If the temperature is in the range defined by:
+
+pwm[1-4]_target    - set target temperature, unit millidegree Celcius
+		     (range 0 - 127000)
+pwm[1-4]_tolerance - tolerance, unit millidegree Celcius (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.
+There are defined steps and times, but not exported by the driver yet.
+
+pwm[1-4]_min_output - minimum fan speed (range 1 - 255), when the temperature
+                      is below defined range.
+pwm[1-4]_stop_time  - how many milliseconds [ms] must elapse to switch
+                      corresponding fan off. (when the temperature was below
+                      defined range).
+
+Note: last two functions are influenced by other control bits, not yet exported
+      by the driver, so a change might not have any effect.
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d
index 83a3836..19b2ed7 100644
--- a/Documentation/hwmon/w83791d
+++ b/Documentation/hwmon/w83791d
@@ -5,7 +5,7 @@
   * Winbond W83791D
     Prefix: 'w83791d'
     Addresses scanned: I2C 0x2c - 0x2f
-    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791D_W83791Gb.pdf
 
 Author: Charles Spirakis <bezaur@gmail.com>
 
@@ -20,6 +20,9 @@
     Chunhao Huang <DZShen@Winbond.com.tw>,
     Rudolf Marek <r.marek@sh.cvut.cz>
 
+Additional contributors:
+    Sven Anders <anders@anduras.de>
+
 Module Parameters
 -----------------
 
@@ -46,7 +49,8 @@
 Description
 -----------
 
-This driver implements support for the Winbond W83791D chip.
+This driver implements support for the Winbond W83791D chip. The W83791G
+chip appears to be the same as the W83791D but is lead free.
 
 Detection of the chip can sometimes be foiled because it can be in an
 internal state that allows no clean access (Bank with ID register is not
@@ -71,34 +75,36 @@
 An alarm is triggered if the voltage has crossed a programmable minimum
 or maximum limit.
 
-Alarms are provided as output from a "realtime status register". The
-following bits are defined:
+The bit ordering for the alarm "realtime status register" and the
+"beep enable registers" are different.
 
-bit - alarm on:
-0  - Vcore
-1  - VINR0
-2  - +3.3VIN
-3  - 5VDD
-4  - temp1
-5  - temp2
-6  - fan1
-7  - fan2
-8  - +12VIN
-9  - -12VIN
-10 - -5VIN
-11 - fan3
-12 - chassis
-13 - temp3
-14 - VINR1
-15 - reserved
-16 - tart1
-17 - tart2
-18 - tart3
-19 - VSB
-20 - VBAT
-21 - fan4
-22 - fan5
-23 - reserved
+in0 (VCORE)  :  alarms: 0x000001 beep_enable: 0x000001
+in1 (VINR0)  :  alarms: 0x000002 beep_enable: 0x002000 <== mismatch
+in2 (+3.3VIN):  alarms: 0x000004 beep_enable: 0x000004
+in3 (5VDD)   :  alarms: 0x000008 beep_enable: 0x000008
+in4 (+12VIN) :  alarms: 0x000100 beep_enable: 0x000100
+in5 (-12VIN) :  alarms: 0x000200 beep_enable: 0x000200
+in6 (-5VIN)  :  alarms: 0x000400 beep_enable: 0x000400
+in7 (VSB)    :  alarms: 0x080000 beep_enable: 0x010000 <== mismatch
+in8 (VBAT)   :  alarms: 0x100000 beep_enable: 0x020000 <== mismatch
+in9 (VINR1)  :  alarms: 0x004000 beep_enable: 0x004000
+temp1        :  alarms: 0x000010 beep_enable: 0x000010
+temp2        :  alarms: 0x000020 beep_enable: 0x000020
+temp3        :  alarms: 0x002000 beep_enable: 0x000002 <== mismatch
+fan1         :  alarms: 0x000040 beep_enable: 0x000040
+fan2         :  alarms: 0x000080 beep_enable: 0x000080
+fan3         :  alarms: 0x000800 beep_enable: 0x000800
+fan4         :  alarms: 0x200000 beep_enable: 0x200000
+fan5         :  alarms: 0x400000 beep_enable: 0x400000
+tart1        :  alarms: 0x010000 beep_enable: 0x040000 <== mismatch
+tart2        :  alarms: 0x020000 beep_enable: 0x080000 <== mismatch
+tart3        :  alarms: 0x040000 beep_enable: 0x100000 <== mismatch
+case_open    :  alarms: 0x001000 beep_enable: 0x001000
+user_enable  :  alarms: -------- beep_enable: 0x800000
+
+*** NOTE: It is the responsibility of user-space code to handle the fact
+that the beep enable and alarm bits are in different positions when using that
+feature of the chip.
 
 When an alarm goes off, you can be warned by a beeping signal through your
 computer speaker. It is possible to enable all beeping globally, or only
@@ -109,5 +115,6 @@
 
 W83791D TODO:
 ---------------
-Provide a patch for per-file alarms as discussed on the mailing list
+Provide a patch for per-file alarms and beep enables as defined in the hwmon
+	documentation (Documentation/hwmon/sysfs-interface)
 Provide a patch for smart-fan control (still need appropriate motherboard/fans)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 5498324..137e993 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -110,6 +110,13 @@
 it will appear as a kernel argument readable via /proc/cmdline by programs
 running once the system is up.
 
+The number of kernel parameters is not limited, but the length of the
+complete command line (parameters including spaces etc.) is limited to
+a fixed number of characters. This limit depends on the architecture
+and is between 256 and 4096 characters. It is defined in the file
+./include/asm/setup.h as COMMAND_LINE_SIZE.
+
+
 	53c7xx=		[HW,SCSI] Amiga SCSI controllers
 			See header of drivers/scsi/53c7xx.c.
 			See also Documentation/scsi/ncr53c7xx.txt.
@@ -1324,7 +1331,7 @@
 	pt.		[PARIDE]
 			See Documentation/paride.txt.
 
-	quiet=		[KNL] Disable log messages
+	quiet		[KNL] Disable most log messages
 
 	r128=		[HW,DRM]
 
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index afac780..dc942ea 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -192,6 +192,17 @@
 arp_interval
 
 	Specifies the ARP link monitoring frequency in milliseconds.
+
+	The ARP monitor works by periodically checking the slave
+	devices to determine whether they have sent or received
+	traffic recently (the precise criteria depends upon the
+	bonding mode, and the state of the slave).  Regular traffic is
+	generated via ARP probes issued for the addresses specified by
+	the arp_ip_target option.
+
+	This behavior can be modified by the arp_validate option,
+	below.
+
 	If ARP monitoring is used in an etherchannel compatible mode
 	(modes 0 and 2), the switch should be configured in a mode
 	that evenly distributes packets across all links. If the
@@ -213,6 +224,54 @@
 	maximum number of targets that can be specified is 16.  The
 	default value is no IP addresses.
 
+arp_validate
+
+	Specifies whether or not ARP probes and replies should be
+	validated in the active-backup mode.  This causes the ARP
+	monitor to examine the incoming ARP requests and replies, and
+	only consider a slave to be up if it is receiving the
+	appropriate ARP traffic.
+
+	Possible values are:
+
+	none or 0
+
+		No validation is performed.  This is the default.
+
+	active or 1
+
+		Validation is performed only for the active slave.
+
+	backup or 2
+
+		Validation is performed only for backup slaves.
+
+	all or 3
+
+		Validation is performed for all slaves.
+
+	For the active slave, the validation checks ARP replies to
+	confirm that they were generated by an arp_ip_target.  Since
+	backup slaves do not typically receive these replies, the
+	validation performed for backup slaves is on the ARP request
+	sent out via the active slave.  It is possible that some
+	switch or network configurations may result in situations
+	wherein the backup slaves do not receive the ARP requests; in
+	such a situation, validation of backup slaves must be
+	disabled.
+
+	This option is useful in network configurations in which
+	multiple bonding hosts are concurrently issuing ARPs to one or
+	more targets beyond a common switch.  Should the link between
+	the switch and target fail (but not the switch itself), the
+	probe traffic generated by the multiple bonding instances will
+	fool the standard ARP monitor into considering the links as
+	still up.  Use of the arp_validate option can resolve this, as
+	the ARP monitor will only consider ARP requests and replies
+	associated with its own instance of bonding.
+
+	This option was added in bonding version 3.1.0.
+
 downdelay
 
 	Specifies the time, in milliseconds, to wait before disabling
diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt
index 44f2f76..18d385c 100644
--- a/Documentation/networking/pktgen.txt
+++ b/Documentation/networking/pktgen.txt
@@ -100,6 +100,7 @@
                          are: IPSRC_RND #IP Source is random (between min/max),
                               IPDST_RND, UDPSRC_RND,
                               UDPDST_RND, MACSRC_RND, MACDST_RND 
+                              MPLS_RND, VID_RND, SVID_RND
 
  pgset "udp_src_min 9"   set UDP source port min, If < udp_src_max, then
                          cycle through the port range.
@@ -125,6 +126,21 @@
 
  pgset "mpls 0"		  turn off mpls (or any invalid argument works too!)
 
+ pgset "vlan_id 77"       set VLAN ID 0-4095
+ pgset "vlan_p 3"         set priority bit 0-7 (default 0)
+ pgset "vlan_cfi 0"       set canonical format identifier 0-1 (default 0)
+
+ pgset "svlan_id 22"      set SVLAN ID 0-4095
+ pgset "svlan_p 3"        set priority bit 0-7 (default 0)
+ pgset "svlan_cfi 0"      set canonical format identifier 0-1 (default 0)
+
+ pgset "vlan_id 9999"     > 4095 remove vlan and svlan tags
+ pgset "svlan 9999"       > 4095 remove svlan tag
+
+
+ pgset "tos XX"           set former IPv4 TOS field (e.g. "tos 28" for AF11 no ECN, default 00)
+ pgset "traffic_class XX" set former IPv6 TRAFFIC CLASS (e.g. "traffic_class B8" for EF no ECN, default 00)
+
  pgset stop    	          aborts injection. Also, ^C aborts generator.
 
 
diff --git a/Documentation/seclvl.txt b/Documentation/seclvl.txt
deleted file mode 100644
index 97274d1..0000000
--- a/Documentation/seclvl.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-BSD Secure Levels Linux Security Module
-Michael A. Halcrow <mike@halcrow.us>
-
-
-Introduction
-
-Under the BSD Secure Levels security model, sets of policies are
-associated with levels. Levels range from -1 to 2, with -1 being the
-weakest and 2 being the strongest. These security policies are
-enforced at the kernel level, so not even the superuser is able to
-disable or circumvent them. This hardens the machine against attackers
-who gain root access to the system.
-
-
-Levels and Policies
-
-Level -1 (Permanently Insecure):
- - Cannot increase the secure level
-
-Level 0 (Insecure):
- - Cannot ptrace the init process
-
-Level 1 (Default):
- - /dev/mem and /dev/kmem are read-only
- - IMMUTABLE and APPEND extended attributes, if set, may not be unset
- - Cannot load or unload kernel modules
- - Cannot write directly to a mounted block device
- - Cannot perform raw I/O operations
- - Cannot perform network administrative tasks
- - Cannot setuid any file
-
-Level 2 (Secure):
- - Cannot decrement the system time
- - Cannot write to any block device, whether mounted or not
- - Cannot unmount any mounted filesystems
-
-
-Compilation
-
-To compile the BSD Secure Levels LSM, seclvl.ko, enable the
-SECURITY_SECLVL configuration option.  This is found under Security
-options -> BSD Secure Levels in the kernel configuration menu.
-
-
-Basic Usage
-
-Once the machine is in a running state, with all the necessary modules
-loaded and all the filesystems mounted, you can load the seclvl.ko
-module:
-
-# insmod seclvl.ko
-
-The module defaults to secure level 1, except when compiled directly
-into the kernel, in which case it defaults to secure level 0. To raise
-the secure level to 2, the administrator writes ``2'' to the
-seclvl/seclvl file under the sysfs mount point (assumed to be /sys in
-these examples):
-
-# echo -n "2" > /sys/seclvl/seclvl
-
-Alternatively, you can initialize the module at secure level 2 with
-the initlvl module parameter:
-
-# insmod seclvl.ko initlvl=2
-
-At this point, it is impossible to remove the module or reduce the
-secure level.  If the administrator wishes to have the option of doing
-so, he must provide a module parameter, sha1_passwd, that specifies
-the SHA1 hash of the password that can be used to reduce the secure
-level to 0.
-
-To generate this SHA1 hash, the administrator can use OpenSSL:
-
-# echo -n "boogabooga" | openssl sha1
-abeda4e0f33defa51741217592bf595efb8d289c
-
-In order to use password-instigated secure level reduction, the SHA1
-crypto module must be loaded or compiled into the kernel:
-
-# insmod sha1.ko
-
-The administrator can then insmod the seclvl module, including the
-SHA1 hash of the password:
-
-# insmod seclvl.ko
-         sha1_passwd=abeda4e0f33defa51741217592bf595efb8d289c
-
-To reduce the secure level, write the password to seclvl/passwd under
-your sysfs mount point:
-
-# echo -n "boogabooga" > /sys/seclvl/passwd
-
-The September 2004 edition of Sys Admin Magazine has an article about
-the BSD Secure Levels LSM.  I encourage you to refer to that article
-for a more in-depth treatment of this security module:
-
-http://www.samag.com/documents/s=9304/sam0409a/0409a.htm
diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
index 867f4c3..39c68f8 100644
--- a/Documentation/usb/error-codes.txt
+++ b/Documentation/usb/error-codes.txt
@@ -98,13 +98,13 @@
 			error, a failure to respond (often caused by
 			device disconnect), or some other fault.
 
--ETIMEDOUT (**)		No response packet received within the prescribed
+-ETIME (**)		No response packet received within the prescribed
 			bus turn-around time.  This error may instead be
 			reported as -EPROTO or -EILSEQ.
 
-			Note that the synchronous USB message functions
-			also use this code to indicate timeout expired
-			before the transfer completed.
+-ETIMEDOUT		Synchronous USB message functions use this code
+			to indicate timeout expired before the transfer
+			completed, and no other error was reported by HC.
 
 -EPIPE (**)		Endpoint stalled.  For non-control endpoints,
 			reset this status with usb_clear_halt().
@@ -163,6 +163,3 @@
 usb_control_msg():
 usb_bulk_msg():
 -ETIMEDOUT		Timeout expired before the transfer completed.
-			In the future this code may change to -ETIME,
-			whose definition is a closer match to this sort
-			of error.
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
index 02b0f7b..a2dee6e 100644
--- a/Documentation/usb/usb-serial.txt
+++ b/Documentation/usb/usb-serial.txt
@@ -433,6 +433,11 @@
   See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
   information on this driver.
 
+AIRcable USB Dongle Bluetooth driver
+  If there is the cdc_acm driver loaded in the system, you will find that the
+  cdc_acm claims the device before AIRcable can. This is simply corrected
+  by unloading both modules and then loading the aircable module before
+  cdc_acm module
 
 Generic Serial driver
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 767a434..2c752d1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -851,7 +851,7 @@
 M:	Douglas_Warzecha@dell.com
 S:	Maintained
 
-DEVICE-MAPPER
+DEVICE-MAPPER  (LVM)
 P:	Alasdair Kergon
 L:	dm-devel@redhat.com
 W:	http://sources.redhat.com/dm
@@ -2062,7 +2062,7 @@
 W:	http://www.linux-ax25.org/
 S:	Maintained
 
-NETWORK BLOCK DEVICE
+NETWORK BLOCK DEVICE (NBD)
 P:	Paul Clements
 M:	Paul.Clements@steeleye.com
 S:	Maintained
@@ -2679,7 +2679,6 @@
 P:	Daniel Drake
 M:	dsd@gentoo.org
 W:	http://softmac.sipsolutions.net/
-L:	softmac-dev@sipsolutions.net
 L:	netdev@vger.kernel.org
 S:	Maintained
 
@@ -2811,6 +2810,12 @@
 L:	linux-kernel@vger.kernel.org ?
 S:	Supported
 
+SPIDERNET NETWORK DRIVER for CELL
+P:	Jim Lewis
+M:	jim@jklewis.com
+L:	netdev@vger.kernel.org
+S:	Supported
+
 SRM (Alpha) environment access
 P:	Jan-Benedict Glaw
 M:	jbglaw@lug-owl.de
@@ -2835,12 +2840,9 @@
 SUPERH (sh)
 P:	Paul Mundt
 M:	lethal@linux-sh.org
-P:	Kazumoto Kojima
-M:	kkojima@rr.iij4u.or.jp
-L:	linuxsh-dev@lists.sourceforge.net
+L:	linuxsh-dev@lists.sourceforge.net (subscribers-only)
 W:	http://www.linux-sh.org
 W:	http://www.m17n.org/linux-sh/
-W:	http://www.rr.iij4u.or.jp/~kkojima/linux-sh4.html
 S:	Maintained
 
 SUPERH64 (sh64)
@@ -3310,6 +3312,12 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
 S:	Maintained
 
+VT1211 HARDWARE MONITOR DRIVER
+P:	Juerg Haefliger
+M:	juergh@gmail.com
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 VT8231 HARDWARE MONITOR DRIVER
 P:	Roger Lucas
 M:	roger@planbit.co.uk
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index b191cc7..7c1e444 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -132,7 +132,7 @@
 	nticks = delta >> FIX_SHIFT;
 
 	while (nticks > 0) {
-		do_timer(regs);
+		do_timer(1);
 #ifndef CONFIG_SMP
 		update_process_times(user_mode(regs));
 #endif
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 622dabd..8871529 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -193,7 +193,7 @@
 	/* We ran out of memory, or some other thing happened to us that
 	   made us unable to handle the page fault gracefully.  */
  out_of_memory:
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f81a623..f9362ee 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -17,6 +17,10 @@
 	  Europe.  There is an ARM Linux project with a web page at
 	  <http://www.arm.linux.org.uk/>.
 
+config GENERIC_TIME
+	bool
+	default n
+
 config MMU
 	bool
 	default y
@@ -51,6 +55,10 @@
 	bool
 	default y
 
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	default y
+
 config HARDIRQS_SW_RESEND
 	bool
 	default y
@@ -91,7 +99,7 @@
 
 config VECTORS_BASE
 	hex
-	default 0xffff0000 if MMU
+	default 0xffff0000 if MMU || CPU_HIGH_VECTOR
 	default DRAM_BASE if REMAP_VECTORS_TO_RAM
 	default 0x00000000
 	help
@@ -198,16 +206,27 @@
 	help
 	  Support for Motorola's i.MX family of processors (MX1, MXL).
 
-config ARCH_IOP3XX
-	bool "IOP3xx-based"
+config ARCH_IOP32X
+	bool "IOP32x-based"
 	depends on MMU
+	select PLAT_IOP
 	select PCI
 	help
-	  Support for Intel's IOP3XX (XScale) family of processors.
+	  Support for Intel's 80219 and IOP32X (XScale) family of
+	  processors.
+
+config ARCH_IOP33X
+	bool "IOP33x-based"
+	depends on MMU
+	select PLAT_IOP
+	select PCI
+	help
+	  Support for Intel's IOP33X (XScale) family of processors.
 
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
 	depends on MMU
+	select GENERIC_TIME
 	help
 	  Support for Intel's IXP4XX (XScale) family of processors.
 
@@ -308,7 +327,9 @@
 
 source "arch/arm/mach-integrator/Kconfig"
 
-source "arch/arm/mach-iop3xx/Kconfig"
+source "arch/arm/mach-iop32x/Kconfig"
+
+source "arch/arm/mach-iop33x/Kconfig"
 
 source "arch/arm/mach-ixp4xx/Kconfig"
 
@@ -348,6 +369,9 @@
 config ARCH_ACORN
 	bool
 
+config PLAT_IOP
+	bool
+
 source arch/arm/mm/Kconfig
 
 #  bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER
@@ -602,6 +626,7 @@
 
 config ALIGNMENT_TRAP
 	bool
+	depends on CPU_CP15_MMU
 	default y if !ARCH_EBSA110
 	help
 	  ARM processors can not fetch/store information which is not
@@ -633,11 +658,12 @@
 	hex "Compressed ROM boot loader BSS address"
 	default "0"
 	help
-	  The base address of 64KiB of read/write memory in the target
-	  for the ROM-able zImage, which must be available while the
-	  decompressor is running.  Platforms which normally make use of
-	  ROM-able zImage formats normally set this to a suitable
-	  value in their defconfig file.
+	  The base address of an area of read/write memory in the target
+	  for the ROM-able zImage which must be available while the
+	  decompressor is running. It must be large enough to hold the
+	  entire decompressed kernel plus an additional 128 KiB.
+	  Platforms which normally make use of ROM-able zImage formats
+	  normally set this to a suitable value in their defconfig file.
 
 	  If ZBOOT_ROM is not enabled, this has no effect.
 
@@ -832,7 +858,7 @@
 
 source "drivers/connector/Kconfig"
 
-if ALIGNMENT_TRAP
+if ALIGNMENT_TRAP || !CPU_CP15_MMU
 source "drivers/mtd/Kconfig"
 endif
 
@@ -844,7 +870,7 @@
 
 source "drivers/acorn/block/Kconfig"
 
-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
+if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
 	|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
 	|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
 	|| ARCH_IXP23XX
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu
index e1574be..f087376 100644
--- a/arch/arm/Kconfig-nommu
+++ b/arch/arm/Kconfig-nommu
@@ -25,6 +25,14 @@
 	hex 'FLASH Size' if SET_MEM_PARAM
 	default 0x00400000
 
+config PROCESSOR_ID
+	hex
+	default 0x00007700
+	depends on !CPU_CP15
+	help
+	  If processor has no CP15 register, this processor ID is
+	  used instead of the auto-probing which utilizes the register.
+
 config REMAP_VECTORS_TO_RAM
 	bool 'Install vectors to the begining of RAM' if DRAM_BASE
 	depends on DRAM_BASE
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 92873cd..2a0b2c8 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -55,7 +55,12 @@
 # This selects how we optimise for the processor.
 tune-$(CONFIG_CPU_ARM610)	:=-mtune=arm610
 tune-$(CONFIG_CPU_ARM710)	:=-mtune=arm710
+tune-$(CONFIG_CPU_ARM7TDMI)	:=-mtune=arm7tdmi
 tune-$(CONFIG_CPU_ARM720T)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM740T)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM9TDMI)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM940T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM946T)	:=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
 tune-$(CONFIG_CPU_ARM920T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM922T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM925T)	:=-mtune=arm9tdmi
@@ -101,7 +106,8 @@
  machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
  textofs-$(CONFIG_ARCH_CLPS711X)   := 0x00028000
  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
- machine-$(CONFIG_ARCH_IOP3XX)	   := iop3xx
+ machine-$(CONFIG_ARCH_IOP32X)	   := iop32x
+ machine-$(CONFIG_ARCH_IOP33X)	   := iop33x
  machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
  machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
  machine-$(CONFIG_ARCH_IXP23XX)    := ixp23xx
@@ -157,6 +163,7 @@
 core-$(CONFIG_VFP)		+= arch/arm/vfp/
 
 # If we have a common platform directory, then include it in the build.
+core-$(CONFIG_PLAT_IOP)		+= arch/arm/plat-iop/
 core-$(CONFIG_ARCH_OMAP)	+= arch/arm/plat-omap/
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 2adc1527..adddc71 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -51,7 +51,11 @@
 endif
 
 ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+ifeq ($(CONFIG_CPU_CP15),y)
 OBJS		+= big-endian.o
+else
+# The endian should be set by h/w design.
+endif
 endif
 
 #
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 14a9ff9..e5ab51b 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -20,11 +20,21 @@
 #ifdef DEBUG
 
 #if defined(CONFIG_DEBUG_ICEDCC)
+
+#ifdef CONFIG_CPU_V6
+		.macro	loadsp, rb
+		.endm
+		.macro	writeb, ch, rb
+		mcr	p14, 0, \ch, c0, c5, 0
+		.endm
+#else
 		.macro	loadsp, rb
 		.endm
 		.macro	writeb, ch, rb
 		mcr	p14, 0, \ch, c0, c1, 0
 		.endm
+#endif
+
 #else
 
 #include <asm/arch/debug-macro.S>
@@ -42,12 +52,6 @@
 		add	\rb, \rb, #0x00010000	@ Ser1
 #endif
 		.endm
-#elif defined(CONFIG_ARCH_IOP331)
-		.macro loadsp, rb
-                mov   	\rb, #0xff000000
-                orr     \rb, \rb, #0x00ff0000
-                orr     \rb, \rb, #0x0000f700   @ location of the UART
-		.endm
 #elif defined(CONFIG_ARCH_S3C2410)
 		.macro loadsp, rb
 		mov	\rb, #0x50000000
@@ -78,9 +82,11 @@
 		kphex	r6, 8		/* processor id */
 		kputc	#':'
 		kphex	r7, 8		/* architecture id */
+#ifdef CONFIG_CPU_CP15
 		kputc	#':'
 		mrc	p15, 0, r0, c1, c0
 		kphex	r0, 8		/* control reg */
+#endif
 		kputc	#'\n'
 		kphex	r5, 8		/* decompressed kernel start */
 		kputc	#'-'
@@ -503,7 +509,11 @@
  */
 
 call_cache_fn:	adr	r12, proc_types
+#ifdef CONFIG_CPU_CP15
 		mrc	p15, 0, r6, c0, c0	@ get processor ID
+#else
+		ldr	r6, =CONFIG_PROCESSOR_ID
+#endif
 1:		ldr	r1, [r12, #0]		@ get value
 		ldr	r2, [r12, #4]		@ get mask
 		eor	r1, r1, r6		@ (real ^ match)
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index ace3fb58..283891c 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -30,6 +30,25 @@
 #include <asm/arch/uncompress.h>
 
 #ifdef CONFIG_DEBUG_ICEDCC
+
+#ifdef CONFIG_CPU_V6
+
+static void icedcc_putc(int ch)
+{
+	int status, i = 0x4000000;
+
+	do {
+		if (--i < 0)
+			return;
+
+		asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
+	} while (status & (1 << 29));
+
+	asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
+}
+
+#else
+
 static void icedcc_putc(int ch)
 {
 	int status, i = 0x4000000;
@@ -44,6 +63,8 @@
 	asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
 }
 
+#endif
+
 #define putc(ch)	icedcc_putc(ch)
 #define flush()	do { } while (0)
 #endif
diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c
index bafe8b1..6d094c1 100644
--- a/arch/arm/common/icst307.c
+++ b/arch/arm/common/icst307.c
@@ -57,7 +57,7 @@
 			break;
 	} while (i < ARRAY_SIZE(idx2s));
 
-	if (i > ARRAY_SIZE(idx2s))
+	if (i >= ARRAY_SIZE(idx2s))
 		return vco;
 
 	vco.s = idx2s[i];
@@ -119,7 +119,7 @@
 			break;
 	} while (i < ARRAY_SIZE(idx2s));
 
-	if (i > ARRAY_SIZE(idx2s))
+	if (i >= ARRAY_SIZE(idx2s))
 		return vco;
 
 	vco.s = idx2s[i];
diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c
index 943ef88..3d377c5 100644
--- a/arch/arm/common/icst525.c
+++ b/arch/arm/common/icst525.c
@@ -55,7 +55,7 @@
 			break;
 	} while (i < ARRAY_SIZE(idx2s));
 
-	if (i > ARRAY_SIZE(idx2s))
+	if (i >= ARRAY_SIZE(idx2s))
 		return vco;
 
 	vco.s = idx2s[i];
@@ -118,7 +118,7 @@
 			break;
 	} while (i < ARRAY_SIZE(idx2s));
 
-	if (i > ARRAY_SIZE(idx2s))
+	if (i >= ARRAY_SIZE(idx2s))
 		return vco;
 
 	vco.s = idx2s[i];
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 4e0dcae..181ef1e 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -121,6 +121,13 @@
 		.offset		= 0,
 		.length		= 0,
 	},
+	{
+		.devid		= LOCOMO_DEVID_SPI,
+		.irq		= {},
+		.name		= "locomo-spi",
+		.offset		= LOCOMO_SPI,
+		.length		= 0x30,
+	},
 };
 
 
@@ -374,7 +381,7 @@
 	struct irqdesc *d;
 	void __iomem *mapbase = get_irq_chipdata(irq);
 
-	req = locomo_readl(mapbase + LOCOMO_SPIIR) & 0x000F;
+	req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F;
 	if (req) {
 		irq = LOCOMO_IRQ_SPI_START;
 		d = irq_desc + irq;
@@ -391,35 +398,35 @@
 {
 	void __iomem *mapbase = get_irq_chipdata(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_SPIWE);
+	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
 	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPIWE);
+	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
 
-	r = locomo_readl(mapbase + LOCOMO_SPIIS);
+	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
 	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPIIS);
+	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
 
-	r = locomo_readl(mapbase + LOCOMO_SPIWE);
+	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
 	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPIWE);
+	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
 }
 
 static void locomo_spi_mask_irq(unsigned int irq)
 {
 	void __iomem *mapbase = get_irq_chipdata(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_SPIIE);
+	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
 	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPIIE);
+	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
 }
 
 static void locomo_spi_unmask_irq(unsigned int irq)
 {
 	void __iomem *mapbase = get_irq_chipdata(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_SPIIE);
+	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
 	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPIIE);
+	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
 }
 
 static struct irq_chip locomo_spi_chip = {
@@ -814,12 +821,15 @@
 	return (struct locomo *)dev_get_drvdata(ldev->dev.parent);
 }
 
-void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir)
+void locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir)
 {
-	struct locomo *lchip = locomo_chip_driver(ldev);
+	struct locomo *lchip = dev_get_drvdata(dev);
 	unsigned long flags;
 	unsigned int r;
 
+	if (!lchip)
+		return;
+
 	spin_lock_irqsave(&lchip->lock, flags);
 
 	r = locomo_readl(lchip->base + LOCOMO_GPD);
@@ -836,12 +846,15 @@
 	spin_unlock_irqrestore(&lchip->lock, flags);
 }
 
-unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits)
+int locomo_gpio_read_level(struct device *dev, unsigned int bits)
 {
-	struct locomo *lchip = locomo_chip_driver(ldev);
+	struct locomo *lchip = dev_get_drvdata(dev);
 	unsigned long flags;
 	unsigned int ret;
 
+	if (!lchip)
+		return -ENODEV;
+
 	spin_lock_irqsave(&lchip->lock, flags);
 	ret = locomo_readl(lchip->base + LOCOMO_GPL);
 	spin_unlock_irqrestore(&lchip->lock, flags);
@@ -850,12 +863,15 @@
 	return ret;
 }
 
-unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits)
+int locomo_gpio_read_output(struct device *dev, unsigned int bits)
 {
-	struct locomo *lchip = locomo_chip_driver(ldev);
+	struct locomo *lchip = dev_get_drvdata(dev);
 	unsigned long flags;
 	unsigned int ret;
 
+	if (!lchip)
+		return -ENODEV;
+
 	spin_lock_irqsave(&lchip->lock, flags);
 	ret = locomo_readl(lchip->base + LOCOMO_GPO);
 	spin_unlock_irqrestore(&lchip->lock, flags);
@@ -864,12 +880,15 @@
 	return ret;
 }
 
-void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set)
+void locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set)
 {
-	struct locomo *lchip = locomo_chip_driver(ldev);
+	struct locomo *lchip = dev_get_drvdata(dev);
 	unsigned long flags;
 	unsigned int r;
 
+	if (!lchip)
+		return;
+
 	spin_lock_irqsave(&lchip->lock, flags);
 
 	r = locomo_readl(lchip->base + LOCOMO_GPO);
@@ -1058,9 +1077,9 @@
 	struct locomo *lchip = locomo_chip_driver(dev);
 
 	if (vr)
-		locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 1);
+		locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 1);
 	else
-		locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 0);
+		locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
 
 	spin_lock_irqsave(&lchip->lock, flags);
 	locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 59b5dde..f412ded 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -40,6 +40,7 @@
 #define SHARPSL_CHARGE_FINISH_TIME             (msecs_to_jiffies(10*60*1000)) /* 10 min */
 #define SHARPSL_BATCHK_TIME                    (msecs_to_jiffies(15*1000))    /* 15 sec */
 #define SHARPSL_BATCHK_TIME_SUSPEND            (60*10)                        /* 10 min */
+
 #define SHARPSL_WAIT_CO_TIME                   15  /* 15 sec */
 #define SHARPSL_WAIT_DISCHARGE_ON              100 /* 100 msec */
 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP   10  /* 10 msec */
@@ -575,6 +576,9 @@
 	while (corgi_enter_suspend(alarm_time,alarm_status,state))
 		{}
 
+	if (sharpsl_pm.machinfo->earlyresume)
+		sharpsl_pm.machinfo->earlyresume();
+
 	dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
 
 	return 0;
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 2948b45..3b4802a 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -126,6 +126,7 @@
 # EP93xx Platforms
 #
 CONFIG_MACH_EDB9302=y
+CONFIG_MACH_EDB9312=y
 CONFIG_MACH_EDB9315=y
 CONFIG_MACH_EDB9315A=y
 CONFIG_MACH_GESBC9312=y
diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/iop32x_defconfig
similarity index 66%
rename from arch/arm/configs/ep80219_defconfig
rename to arch/arm/configs/iop32x_defconfig
index 3c73b70..0d67f66 100644
--- a/arch/arm/configs/ep80219_defconfig
+++ b/arch/arm/configs/iop32x_defconfig
@@ -1,50 +1,63 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:34:12 2005
+# Linux kernel version: 2.6.18-rc7
+# Tue Sep 19 00:30:18 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=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_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=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_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -52,24 +65,52 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # System Type
 #
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+CONFIG_ARCH_IOP32X=y
+# CONFIG_ARCH_IOP33X is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
@@ -77,28 +118,19 @@
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
 
 #
-# IOP3xx Implementation Options
+# IOP32x Implementation Options
 #
 
 #
-# IOP3xx Platform Types
+# IOP32x Platform Types
 #
-# CONFIG_ARCH_IQ80321 is not set
+CONFIG_MACH_GLANTANK=y
+CONFIG_ARCH_IQ80321=y
 CONFIG_ARCH_IQ31244=y
-# CONFIG_ARCH_IQ80331 is not set
-# CONFIG_MACH_IQ80332 is not set
-CONFIG_ARCH_EP80219=y
-CONFIG_ARCH_IOP321=y
-# CONFIG_ARCH_IOP331 is not set
-
-#
-# IOP3xx Chipset Features
-#
+CONFIG_MACH_N2100=y
+CONFIG_PLAT_IOP=y
 
 #
 # Processor Type
@@ -109,7 +141,6 @@
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -121,8 +152,7 @@
 # Bus support
 #
 CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -133,6 +163,19 @@
 # Kernel Features
 #
 # CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -140,7 +183,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp"
 # CONFIG_XIP_KERNEL is not set
 
 #
@@ -166,6 +209,93 @@
 # Power management options
 #
 # CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# 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 is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -177,6 +307,13 @@
 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
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -200,6 +337,7 @@
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -225,18 +363,18 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xf0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
 # CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -245,7 +383,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -261,6 +398,11 @@
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -272,7 +414,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -284,17 +425,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -305,6 +438,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -316,6 +450,7 @@
 # CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -330,10 +465,12 @@
 # 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
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP 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
@@ -344,25 +481,19 @@
 # CONFIG_SCSI_DPT_I2O 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_BUSLOGIC is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -377,8 +508,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 # CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=y
@@ -392,6 +522,9 @@
 # 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
@@ -404,71 +537,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -481,14 +551,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 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_SMC91X is not set
+# CONFIG_DM9000 is not set
 
 #
 # Tulip family network device support
@@ -526,16 +603,23 @@
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI 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
 
 #
 # 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
@@ -558,6 +642,8 @@
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -595,7 +681,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -603,6 +688,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -610,7 +696,9 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -618,6 +706,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -631,8 +720,8 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -647,6 +736,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -671,14 +761,13 @@
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
-CONFIG_I2C_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_IOP3XX=y
+# 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_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -689,15 +778,45 @@
 # CONFIG_I2C_PCA_ISA is not set
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
@@ -712,36 +831,45 @@
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
 #
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -751,6 +879,7 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
 
 #
@@ -758,6 +887,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -769,7 +899,125 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
+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=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=y
+# 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_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_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
+
+#
+# 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_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_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
 
 #
 # USB Gadget Support
@@ -782,10 +1030,17 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # 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
@@ -795,22 +1050,22 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT 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 is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -830,12 +1085,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -850,8 +1103,9 @@
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -868,16 +1122,19 @@
 #
 CONFIG_NFS_FS=y
 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=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -886,6 +1143,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -905,6 +1163,7 @@
 # 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
 
 #
@@ -921,11 +1180,34 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# 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_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
 
 #
 # Security options
@@ -946,7 +1228,9 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iop33x_defconfig
similarity index 74%
rename from arch/arm/configs/iq80331_defconfig
rename to arch/arm/configs/iop33x_defconfig
index 46c79e1..2a8fc15 100644
--- a/arch/arm/configs/iq80331_defconfig
+++ b/arch/arm/configs/iop33x_defconfig
@@ -1,50 +1,63 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 15:13:37 2005
+# Linux kernel version: 2.6.18-rc7
+# Tue Sep 19 00:30:42 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=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_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=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_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -52,24 +65,52 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # System Type
 #
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+CONFIG_ARCH_IOP33X=y
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
@@ -77,28 +118,17 @@
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
 
 #
-# IOP3xx Implementation Options
+# IOP33x Implementation Options
 #
 
 #
-# IOP3xx Platform Types
+# IOP33x Platform Types
 #
-# CONFIG_ARCH_IQ80321 is not set
-# CONFIG_ARCH_IQ31244 is not set
 CONFIG_ARCH_IQ80331=y
-# CONFIG_MACH_IQ80332 is not set
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP331=y
-
-#
-# IOP3xx Chipset Features
-#
-CONFIG_IOP331_STEPD=y
+CONFIG_MACH_IQ80332=y
+CONFIG_PLAT_IOP=y
 
 #
 # Processor Type
@@ -109,7 +139,6 @@
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -121,8 +150,7 @@
 # Bus support
 #
 CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -133,6 +161,19 @@
 # Kernel Features
 #
 # CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -140,7 +181,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp"
 # CONFIG_XIP_KERNEL is not set
 
 #
@@ -166,6 +207,93 @@
 # Power management options
 #
 # CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# 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 is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -177,6 +305,13 @@
 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
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -200,6 +335,7 @@
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -222,6 +358,7 @@
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
@@ -229,18 +366,18 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xc0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
 CONFIG_MTD_PHYSMAP_BANKWIDTH=1
 # CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -249,7 +386,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -265,6 +401,11 @@
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -276,7 +417,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -288,17 +428,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -309,6 +441,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -320,6 +453,7 @@
 # CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -334,10 +468,12 @@
 # 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
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP 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
@@ -348,25 +484,19 @@
 # CONFIG_SCSI_DPT_I2O 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_BUSLOGIC is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -381,8 +511,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 # CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=y
@@ -396,6 +525,9 @@
 # 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
@@ -408,71 +540,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -485,6 +554,10 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+
+#
 # Ethernet (10 or 100Mbit)
 #
 # CONFIG_NET_ETHERNET is not set
@@ -501,14 +574,20 @@
 # 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_TIGON3 is not set
+# CONFIG_BNX2 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
@@ -531,6 +610,8 @@
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -568,7 +649,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -576,6 +656,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -583,7 +664,9 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -591,6 +674,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -604,8 +688,8 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -620,6 +704,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -644,14 +729,13 @@
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
-CONFIG_I2C_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_IOP3XX=y
+# 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_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -662,15 +746,45 @@
 # CONFIG_I2C_PCA_ISA is not set
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
@@ -685,36 +799,45 @@
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
 #
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -724,6 +847,7 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
 
 #
@@ -731,6 +855,7 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -742,9 +867,14 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -755,10 +885,17 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # 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
@@ -768,22 +905,22 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT 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 is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -803,12 +940,10 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -834,16 +969,19 @@
 #
 CONFIG_NFS_FS=y
 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=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -852,6 +990,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -871,6 +1010,7 @@
 # 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
 
 #
@@ -887,11 +1027,34 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# 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_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
 
 #
 # Security options
@@ -912,5 +1075,7 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig
deleted file mode 100644
index 3246716..0000000
--- a/arch/arm/configs/iq31244_defconfig
+++ /dev/null
@@ -1,922 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 02:10:38 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-# CONFIG_ARCH_IQ80321 is not set
-CONFIG_ARCH_IQ31244=y
-# CONFIG_ARCH_IQ80331 is not set
-# CONFIG_MACH_IQ80332 is not set
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP321=y
-# CONFIG_ARCH_IOP331 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xf0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# 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_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 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
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-# CONFIG_MD_LINEAR is not set
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# 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_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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_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
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA 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_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB 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
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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 is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig
deleted file mode 100644
index b000da7..0000000
--- a/arch/arm/configs/iq80321_defconfig
+++ /dev/null
@@ -1,843 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 13:24:10 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-CONFIG_ARCH_IQ80321=y
-# CONFIG_ARCH_IQ31244 is not set
-# CONFIG_ARCH_IQ80331 is not set
-# CONFIG_MACH_IQ80332 is not set
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP321=y
-# CONFIG_ARCH_IOP331 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xf0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# 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_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_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
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA 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_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB 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
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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 is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig
deleted file mode 100644
index 11959b7..0000000
--- a/arch/arm/configs/iq80332_defconfig
+++ /dev/null
@@ -1,916 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 17:33:39 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-# CONFIG_ARCH_IQ80321 is not set
-# CONFIG_ARCH_IQ31244 is not set
-# CONFIG_ARCH_IQ80331 is not set
-CONFIG_MACH_IQ80332=y
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP331=y
-
-#
-# IOP3xx Chipset Features
-#
-# CONFIG_IOP331_STEPD is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_GEOMETRY is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xc0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# 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_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 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
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# 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_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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_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
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA 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_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB 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
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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 is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index f20814e..a832226 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,14 +1,19 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-git9
-# Sun Jun 25 23:56:32 2006
+# Linux kernel version: 2.6.18
+# Wed Sep 20 20:27:31 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -26,14 +31,15 @@
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -46,6 +52,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
@@ -84,7 +92,7 @@
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
@@ -94,7 +102,8 @@
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
 # CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP23XX is not set
@@ -122,13 +131,18 @@
 CONFIG_ARCH_S3C2440=y
 CONFIG_SMDK2440_CPU2440=y
 CONFIG_SMDK2440_CPU2442=y
+CONFIG_MACH_S3C2413=y
 CONFIG_MACH_SMDK2413=y
 CONFIG_MACH_VR1000=y
 CONFIG_MACH_RX3715=y
 CONFIG_MACH_OTOM=y
 CONFIG_MACH_NEXCODER_2440=y
+CONFIG_MACH_VSTMS=y
 CONFIG_S3C2410_CLOCK=y
+CONFIG_S3C2410_PM=y
+CONFIG_CPU_S3C2410_DMA=y
 CONFIG_CPU_S3C2410=y
+CONFIG_S3C2412_PM=y
 CONFIG_CPU_S3C2412=y
 CONFIG_CPU_S3C244X=y
 CONFIG_CPU_S3C2440=y
@@ -156,7 +170,7 @@
 CONFIG_CPU_32=y
 CONFIG_CPU_ARM920T=y
 CONFIG_CPU_ARM926T=y
-CONFIG_CPU_32v4=y
+CONFIG_CPU_32v4T=y
 CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV4T=y
 CONFIG_CPU_ABRT_EV5TJ=y
@@ -200,6 +214,7 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -304,7 +319,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
 
@@ -460,6 +474,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
@@ -640,6 +655,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
@@ -716,6 +732,7 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 CONFIG_S3C2410_RTC=y
 # CONFIG_DTLK is not set
@@ -857,12 +874,12 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
-CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
@@ -995,7 +1012,7 @@
 # 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
@@ -1095,6 +1112,7 @@
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -1202,14 +1220,19 @@
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# 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_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
@@ -1251,3 +1274,4 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
index 33c5568..ecf4f94 100644
--- a/arch/arm/kernel/apm.c
+++ b/arch/arm/kernel/apm.c
@@ -25,6 +25,7 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/completion.h>
+#include <linux/kthread.h>
 
 #include <asm/apm.h> /* apm_power_info */
 #include <asm/system.h>
@@ -80,7 +81,7 @@
  */
 static int suspends_pending;
 static int apm_disabled;
-static int arm_apm_active;
+static struct task_struct *kapmd_tsk;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
@@ -97,7 +98,6 @@
  * to be suspending the system.
  */
 static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
-static DECLARE_COMPLETION(kapmd_exit);
 static DEFINE_SPINLOCK(kapmd_queue_lock);
 static struct apm_queue kapmd_queue;
 
@@ -468,16 +468,13 @@
 
 static int kapmd(void *arg)
 {
-	daemonize("kapmd");
-	current->flags |= PF_NOFREEZE;
-
 	do {
 		apm_event_t event;
 
 		wait_event_interruptible(kapmd_wait,
-				!queue_empty(&kapmd_queue) || !arm_apm_active);
+				!queue_empty(&kapmd_queue) || kthread_should_stop());
 
-		if (!arm_apm_active)
+		if (kthread_should_stop())
 			break;
 
 		spin_lock_irq(&kapmd_queue_lock);
@@ -508,7 +505,7 @@
 		}
 	} while (1);
 
-	complete_and_exit(&kapmd_exit, 0);
+	return 0;
 }
 
 static int __init apm_init(void)
@@ -520,13 +517,14 @@
 		return -ENODEV;
 	}
 
-	arm_apm_active = 1;
-
-	ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
-	if (ret < 0) {
-		arm_apm_active = 0;
+	kapmd_tsk = kthread_create(kapmd, NULL, "kapmd");
+	if (IS_ERR(kapmd_tsk)) {
+		ret = PTR_ERR(kapmd_tsk);
+		kapmd_tsk = NULL;
 		return ret;
 	}
+	kapmd_tsk->flags |= PF_NOFREEZE;
+	wake_up_process(kapmd_tsk);
 
 #ifdef CONFIG_PROC_FS
 	create_proc_info_entry("apm", 0, NULL, apm_get_info);
@@ -535,10 +533,7 @@
 	ret = misc_register(&apm_device);
 	if (ret != 0) {
 		remove_proc_entry("apm", NULL);
-
-		arm_apm_active = 0;
-		wake_up(&kapmd_wait);
-		wait_for_completion(&kapmd_exit);
+		kthread_stop(kapmd_tsk);
 	}
 
 	return ret;
@@ -549,9 +544,7 @@
 	misc_deregister(&apm_device);
 	remove_proc_entry("apm", NULL);
 
-	arm_apm_active = 0;
-	wake_up(&kapmd_wait);
-	wait_for_completion(&kapmd_exit);
+	kthread_stop(kapmd_tsk);
 }
 
 module_init(apm_init);
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index a5747e5..5617566 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -21,6 +21,36 @@
 
 #if defined(CONFIG_DEBUG_ICEDCC)
 		@@ debug using ARM EmbeddedICE DCC channel
+
+#if defined(CONFIG_CPU_V6)
+
+		.macro	addruart, rx
+		.endm
+
+		.macro	senduart, rd, rx
+		mcr	p14, 0, \rd, c0, c5, 0
+		.endm
+
+		.macro	busyuart, rd, rx
+1001:
+		mrc	p14, 0, \rx, c0, c1, 0
+		tst	\rx, #0x20000000
+		beq	1001b
+		.endm
+
+		.macro	waituart, rd, rx
+		mov	\rd, #0x2000000
+1001:
+		subs	\rd, \rd, #1
+		bmi	1002f
+		mrc	p14, 0, \rx, c0, c1, 0
+		tst	\rx, #0x20000000
+		bne	1001b
+1002:
+		.endm
+
+#else
+
 		.macro	addruart, rx
 		.endm
 
@@ -46,9 +76,12 @@
 		bne	1001b
 1002:
 		.endm
+
+#endif	/* CONFIG_CPU_V6 */
+
 #else
 #include <asm/arch/debug-macro.S>
-#endif
+#endif	/* CONFIG_DEBUG_ICEDCC */
 
 /*
  * Useful debugging routines
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index de4e331..bd623b7 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -191,6 +191,9 @@
 __irq_svc:
 	svc_entry
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
 #ifdef CONFIG_PREEMPT
 	get_thread_info tsk
 	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
@@ -211,6 +214,10 @@
 #endif
 	ldr	r0, [sp, #S_PSR]		@ irqs are already disabled
 	msr	spsr_cxsf, r0
+#ifdef CONFIG_TRACE_IRQFLAGS
+	tst	r0, #PSR_I_BIT
+	bleq	trace_hardirqs_on
+#endif
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 
 	.ltorg
@@ -398,6 +405,9 @@
 __irq_usr:
 	usr_entry
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
 	get_thread_info tsk
 #ifdef CONFIG_PREEMPT
 	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
@@ -412,6 +422,9 @@
 	teq	r0, r7
 	strne	r0, [r0, -r0]
 #endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+#endif
 
 	mov	why, #0
 	b	ret_to_user
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index ac9eb3d..f359a18 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -9,7 +9,6 @@
  * published by the Free Software Foundation.
  *
  *  Common kernel startup code (non-paged MM)
- *    for 32-bit CPUs which has a process ID register(CP15).
  *
  */
 #include <linux/linkage.h>
@@ -40,7 +39,11 @@
 ENTRY(stext)
 	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
 						@ and irqs disabled
+#ifndef CONFIG_CPU_CP15
+	ldr	r9, =CONFIG_PROCESSOR_ID
+#else
 	mrc	p15, 0, r9, c0, c0		@ get processor id
+#endif
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
 	beq	__error_p				@ yes, error 'p'
@@ -58,6 +61,7 @@
  */
 	.type	__after_proc_init, %function
 __after_proc_init:
+#ifdef CONFIG_CPU_CP15
 	mrc	p15, 0, r0, c1, c0, 0		@ read control reg
 #ifdef CONFIG_ALIGNMENT_TRAP
 	orr	r0, r0, #CR_A
@@ -73,7 +77,13 @@
 #ifdef CONFIG_CPU_ICACHE_DISABLE
 	bic	r0, r0, #CR_I
 #endif
+#ifdef CONFIG_CPU_HIGH_VECTOR
+	orr	r0, r0, #CR_V
+#else
+	bic	r0, r0, #CR_V
+#endif
 	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
+#endif /* CONFIG_CPU_CP15 */
 
 	mov	pc, r13				@ clear the BSS and jump
 						@ to start_kernel
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 298363d..1b06158 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -2,6 +2,7 @@
  *  linux/arch/arm/kernel/module.c
  *
  *  Copyright (C) 2002 Russell King.
+ *  Modified for nommu by Hyok S. Choi
  *
  * 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
@@ -32,6 +33,7 @@
 #define MODULE_START	(((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK)
 #endif
 
+#ifdef CONFIG_MMU
 void *module_alloc(unsigned long size)
 {
 	struct vm_struct *area;
@@ -46,6 +48,12 @@
 
 	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
 }
+#else /* CONFIG_MMU */
+void *module_alloc(unsigned long size)
+{
+	return size == 0 ? NULL : vmalloc(size);
+}
+#endif /* !CONFIG_MMU */
 
 void module_free(struct module *module, void *region)
 {
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 3079535..bf35c17 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -221,16 +221,26 @@
 		processor_modes[processor_mode(regs)],
 		thumb_mode(regs) ? " (T)" : "",
 		get_fs() == get_ds() ? "kernel" : "user");
+#if CONFIG_CPU_CP15
 	{
-		unsigned int ctrl, transbase, dac;
+		unsigned int ctrl;
 		  __asm__ (
 		"	mrc p15, 0, %0, c1, c0\n"
-		"	mrc p15, 0, %1, c2, c0\n"
-		"	mrc p15, 0, %2, c3, c0\n"
-		: "=r" (ctrl), "=r" (transbase), "=r" (dac));
-		printk("Control: %04X  Table: %08X  DAC: %08X\n",
-		  	ctrl, transbase, dac);
+		: "=r" (ctrl));
+		printk("Control: %04X\n", ctrl);
 	}
+#ifdef CONFIG_CPU_CP15_MMU
+	{
+		unsigned int transbase, dac;
+		  __asm__ (
+		"	mrc p15, 0, %0, c2, c0\n"
+		"	mrc p15, 0, %1, c3, c0\n"
+		: "=r" (transbase), "=r" (dac));
+		printk("Table: %08X  DAC: %08X\n",
+		  	transbase, dac);
+	}
+#endif
+#endif
 }
 
 void show_regs(struct pt_regs * regs)
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 09a67d7..f7d5165 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -69,10 +69,12 @@
  */
 int (*set_rtc)(void);
 
+#ifndef CONFIG_GENERIC_TIME
 static unsigned long dummy_gettimeoffset(void)
 {
 	return 0;
 }
+#endif
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -230,6 +232,7 @@
 #define	do_leds()
 #endif
 
+#ifndef CONFIG_GENERIC_TIME
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long flags;
@@ -291,6 +294,7 @@
 }
 
 EXPORT_SYMBOL(do_settimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
 
 /**
  * save_time_delta - Save the offset between system time and RTC time
@@ -333,7 +337,7 @@
 	profile_tick(CPU_PROFILING, regs);
 	do_leds();
 	do_set_rtc();
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
@@ -500,8 +504,10 @@
 
 void __init time_init(void)
 {
+#ifndef CONFIG_GENERIC_TIME
 	if (system_timer->offset == NULL)
 		system_timer->offset = dummy_gettimeoffset;
+#endif
 	system_timer->init();
 
 #ifdef CONFIG_NO_IDLE_HZ
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index aeeed80..bede380 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -191,7 +191,7 @@
 	if (tsk != current)
 		fp = thread_saved_fp(tsk);
 	else
-		asm("mov%? %0, fp" : "=r" (fp));
+		asm("mov %0, fp" : "=r" (fp) : : "cc");
 
 	c_backtrace(fp, 0x10);
 	barrier();
diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c
index 0985b1c..dcf6136 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200.c
+++ b/arch/arm/mach-at91rm9200/at91rm9200.c
@@ -17,6 +17,7 @@
 
 #include <asm/hardware.h>
 #include "generic.h"
+#include "clock.h"
 
 static struct map_desc at91rm9200_io_desc[] __initdata = {
 	{
@@ -26,87 +27,224 @@
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= AT91_VA_BASE_SPI,
-		.pfn		= __phys_to_pfn(AT91_BASE_SPI),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_SSC2,
-		.pfn		= __phys_to_pfn(AT91_BASE_SSC2),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_SSC1,
-		.pfn		= __phys_to_pfn(AT91_BASE_SSC1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_SSC0,
-		.pfn		= __phys_to_pfn(AT91_BASE_SSC0),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_US3,
-		.pfn		= __phys_to_pfn(AT91_BASE_US3),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_US2,
-		.pfn		= __phys_to_pfn(AT91_BASE_US2),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_US1,
-		.pfn		= __phys_to_pfn(AT91_BASE_US1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_US0,
-		.pfn		= __phys_to_pfn(AT91_BASE_US0),
+		.pfn		= __phys_to_pfn(AT91RM9200_BASE_SPI),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= AT91_VA_BASE_EMAC,
-		.pfn		= __phys_to_pfn(AT91_BASE_EMAC),
+		.pfn		= __phys_to_pfn(AT91RM9200_BASE_EMAC),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= AT91_VA_BASE_TWI,
-		.pfn		= __phys_to_pfn(AT91_BASE_TWI),
+		.pfn		= __phys_to_pfn(AT91RM9200_BASE_TWI),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= AT91_VA_BASE_MCI,
-		.pfn		= __phys_to_pfn(AT91_BASE_MCI),
+		.pfn		= __phys_to_pfn(AT91RM9200_BASE_MCI),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= AT91_VA_BASE_UDP,
-		.pfn		= __phys_to_pfn(AT91_BASE_UDP),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_TCB1,
-		.pfn		= __phys_to_pfn(AT91_BASE_TCB1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= AT91_VA_BASE_TCB0,
-		.pfn		= __phys_to_pfn(AT91_BASE_TCB0),
+		.pfn		= __phys_to_pfn(AT91RM9200_BASE_UDP),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= AT91_SRAM_VIRT_BASE,
-		.pfn		= __phys_to_pfn(AT91_SRAM_BASE),
-		.length		= AT91_SRAM_SIZE,
+		.pfn		= __phys_to_pfn(AT91RM9200_SRAM_BASE),
+		.length		= AT91RM9200_SRAM_SIZE,
 		.type		= MT_DEVICE,
 	},
 };
 
-void __init at91rm9200_map_io(void)
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk udc_clk = {
+	.name		= "udc_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_UDP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+	.name		= "ohci_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_UHP,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk ether_clk = {
+	.name		= "ether_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_EMAC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+	.name		= "mci_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_MCI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+	.name		= "twi_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_TWI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+	.name		= "usart0_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US0,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+	.name		= "usart1_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US1,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+	.name		= "usart2_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US2,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+	.name		= "usart3_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_US3,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi_clk = {
+	.name		= "spi_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_SPI,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOA,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOB,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+	.name		= "pioC_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOC,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioD_clk = {
+	.name		= "pioD_clk",
+	.pmc_mask	= 1 << AT91RM9200_ID_PIOD,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+	&pioA_clk,
+	&pioB_clk,
+	&pioC_clk,
+	&pioD_clk,
+	&usart0_clk,
+	&usart1_clk,
+	&usart2_clk,
+	&usart3_clk,
+	&mmc_clk,
+	&udc_clk,
+	&twi_clk,
+	&spi_clk,
+	// ssc 0 .. ssc2
+	// tc0 .. tc5
+	&ohci_clk,
+	&ether_clk,
+	// irq0 .. irq6
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+	.name		= "pck0",
+	.pmc_mask	= AT91_PMC_PCK0,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 0,
+};
+static struct clk pck1 = {
+	.name		= "pck1",
+	.pmc_mask	= AT91_PMC_PCK1,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 1,
+};
+static struct clk pck2 = {
+	.name		= "pck2",
+	.pmc_mask	= AT91_PMC_PCK2,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 2,
+};
+static struct clk pck3 = {
+	.name		= "pck3",
+	.pmc_mask	= AT91_PMC_PCK3,
+	.type		= CLK_TYPE_PROGRAMMABLE,
+	.id		= 3,
+};
+
+static void __init at91rm9200_register_clocks(void)
 {
-	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+		clk_register(periph_clocks[i]);
+
+	clk_register(&pck0);
+	clk_register(&pck1);
+	clk_register(&pck2);
+	clk_register(&pck3);
 }
 
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91rm9200_gpio[] = {
+	{
+		.id		= AT91RM9200_ID_PIOA,
+		.offset		= AT91_PIOA,
+		.clock		= &pioA_clk,
+	}, {
+		.id		= AT91RM9200_ID_PIOB,
+		.offset		= AT91_PIOB,
+		.clock		= &pioB_clk,
+	}, {
+		.id		= AT91RM9200_ID_PIOC,
+		.offset		= AT91_PIOC,
+		.clock		= &pioC_clk,
+	}, {
+		.id		= AT91RM9200_ID_PIOD,
+		.offset		= AT91_PIOD,
+		.clock		= &pioD_clk,
+	}
+};
+
+/* --------------------------------------------------------------------
+ *  AT91RM9200 processor initialization
+ * -------------------------------------------------------------------- */
+void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks)
+{
+	/* Map peripherals */
+	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
+
+	/* Init clock subsystem */
+	at91_clock_init(main_clock);
+
+	/* Register the processor-specific clocks */
+	at91rm9200_register_clocks();
+
+	/* Initialize GPIO subsystem */
+	at91_gpio_init(at91rm9200_gpio, banks);
+}
+
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
 /*
  * The default interrupt priority levels (0 = lowest, 7 = highest).
  */
@@ -145,10 +283,14 @@
 	0	/* Advanced Interrupt Controller (IRQ6) */
 };
 
-void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS])
+void __init at91rm9200_init_interrupts(unsigned int priority[NR_AIC_IRQS])
 {
 	if (!priority)
 		priority = at91rm9200_default_irq_priority;
 
+	/* Initialize the AIC interrupt controller */
 	at91_aic_init(priority);
+
+	/* Enable GPIO interrupts */
+	at91_gpio_irq_setup();
 }
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91rm9200/board-1arm.c
index dc79e09..36eecd7 100644
--- a/arch/arm/mach-at91rm9200/board-1arm.c
+++ b/arch/arm/mach-at91rm9200/board-1arm.c
@@ -34,20 +34,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init onearm_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -62,15 +53,18 @@
 
 static void __init onearm_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 18.432 MHz crystal */
-	at91_clock_init(18432000);
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_PQFP);
 
 	/* Setup the serial ports and console */
 	at91_init_serial(&onearm_uart_config);
 }
 
+static void __init onearm_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata onearm_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC4,
 	.is_rmii	= 1,
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c
index 2c138b5..50e5136 100644
--- a/arch/arm/mach-at91rm9200/board-carmeva.c
+++ b/arch/arm/mach-at91rm9200/board-carmeva.c
@@ -35,20 +35,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init carmeva_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -63,15 +54,19 @@
 
 static void __init carmeva_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 20.000 MHz crystal */
-	at91_clock_init(20000000);
+	/* Initialize processor: 20.000 MHz crystal */
+	at91rm9200_initialize(20000000, AT91RM9200_BGA);
 
 	/* Setup the serial ports and console */
 	at91_init_serial(&carmeva_uart_config);
 }
 
+static void __init carmeva_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
+
 static struct at91_eth_data __initdata carmeva_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC4,
 	.is_rmii	= 1,
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 794d3fb..8eeae49 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -34,20 +34,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init csb337_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -62,10 +53,8 @@
 
 static void __init csb337_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 3.6864 MHz crystal */
-	at91_clock_init(3686400);
+	/* Initialize processor: 3.6864 MHz crystal */
+	at91rm9200_initialize(3686400, AT91RM9200_BGA);
 
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
@@ -74,6 +63,11 @@
 	at91_init_serial(&csb337_uart_config);
 }
 
+static void __init csb337_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata csb337_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC2,
 	.is_rmii	= 0,
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index c8b6f33..a29fa0e8 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -33,20 +33,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init csb637_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -61,10 +52,8 @@
 
 static void __init csb637_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 3.6864 MHz crystal */
-	at91_clock_init(3686400);
+	/* Initialize processor: 3.6864 MHz crystal */
+	at91rm9200_initialize(3686400, AT91RM9200_BGA);
 
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
@@ -73,6 +62,11 @@
 	at91_init_serial(&csb637_uart_config);
 }
 
+static void __init csb637_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata csb637_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC0,
 	.is_rmii	= 0,
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 6587303..c699f39 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -37,20 +37,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init dk_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -65,10 +56,8 @@
 
 static void __init dk_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 18.432 MHz crystal */
-	at91_clock_init(18432000);
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_BGA);
 
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
@@ -77,6 +66,11 @@
 	at91_init_serial(&dk_uart_config);
 }
 
+static void __init dk_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata dk_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC4,
 	.is_rmii	= 1,
@@ -128,6 +122,29 @@
 #endif
 };
 
+static struct mtd_partition __initdata dk_nand_partition[] = {
+	{
+		.name	= "NAND Partition 1",
+		.offset	= 0,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(dk_nand_partition);
+	return dk_nand_partition;
+}
+
+static struct at91_nand_data __initdata dk_nand_data = {
+	.ale		= 22,
+	.cle		= 21,
+	.det_pin	= AT91_PIN_PB1,
+	.rdy_pin	= AT91_PIN_PC2,
+	// .enable_pin	= ... not there
+	.partition_info	= nand_partitions,
+};
+
 static void __init dk_board_init(void)
 {
 	/* Serial */
@@ -153,6 +170,8 @@
 	at91_set_gpio_output(AT91_PIN_PB7, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
 	at91_add_device_mmc(&dk_mmc_data);
 #endif
+	/* NAND */
+	at91_add_device_nand(&dk_nand_data);
 	/* VGA */
 //	dk_add_device_video();
 }
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c
index a3e2df9..c6e0d51 100644
--- a/arch/arm/mach-at91rm9200/board-eb9200.c
+++ b/arch/arm/mach-at91rm9200/board-eb9200.c
@@ -35,20 +35,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init eb9200_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -63,15 +54,18 @@
 
 static void __init eb9200_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 18.432 MHz crystal */
-	at91_clock_init(18432000);
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_BGA);
 
 	/* Setup the serial ports and console */
 	at91_init_serial(&eb9200_uart_config);
 }
 
+static void __init eb9200_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata eb9200_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC4,
 	.is_rmii	= 1,
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index 8681923..830eb79 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -37,20 +37,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init ek_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -65,10 +56,8 @@
 
 static void __init ek_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 18.432 MHz crystal */
-	at91_clock_init(18432000);
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_BGA);
 
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
@@ -77,6 +66,11 @@
 	at91_init_serial(&ek_uart_config);
 }
 
+static void __init ek_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata ek_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC4,
 	.is_rmii	= 1,
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c
index bf760c5..91e3019 100644
--- a/arch/arm/mach-at91rm9200/board-kafa.c
+++ b/arch/arm/mach-at91rm9200/board-kafa.c
@@ -34,20 +34,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init kafa_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -62,10 +53,8 @@
 
 static void __init kafa_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 18.432 MHz crystal */
-	at91_clock_init(18432000);
+	/* Initialize processor: 18.432 MHz crystal */
+	at91rm9200_initialize(18432000, AT91RM9200_PQFP);
 
 	/* Set up the LEDs */
 	at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
@@ -74,6 +63,11 @@
 	at91_init_serial(&kafa_uart_config);
 }
 
+static void __init kafa_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata kafa_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC4,
 	.is_rmii	= 0,
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c
index f06d2b5..272fe43b 100644
--- a/arch/arm/mach-at91rm9200/board-kb9202.c
+++ b/arch/arm/mach-at91rm9200/board-kb9202.c
@@ -35,20 +35,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init kb9202_init_irq(void)
-{
-	/* Initialize AIC controller */
-	at91rm9200_init_irq(NULL);
-
-	/* Set up the GPIO interrupts */
-	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -63,10 +54,8 @@
 
 static void __init kb9202_map_io(void)
 {
-	at91rm9200_map_io();
-
-	/* Initialize clocks: 10 MHz crystal */
-	at91_clock_init(10000000);
+	/* Initialize processor: 10 MHz crystal */
+	at91rm9200_initialize(10000000, AT91RM9200_PQFP);
 
 	/* Set up the LEDs */
 	at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
@@ -75,6 +64,11 @@
 	at91_init_serial(&kb9202_uart_config);
 }
 
+static void __init kb9202_init_irq(void)
+{
+	at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata kb9202_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PB29,
 	.is_rmii	= 0,
@@ -95,6 +89,29 @@
 	.wire4		= 1,
 };
 
+static struct mtd_partition __initdata kb9202_nand_partition[] = {
+	{
+		.name	= "nand_fs",
+		.offset	= 0,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
+	return kb9202_nand_partition;
+}
+
+static struct at91_nand_data __initdata kb9202_nand_data = {
+	.ale		= 22,
+	.cle		= 21,
+	// .det_pin	= ... not there
+	.rdy_pin	= AT91_PIN_PC29,
+	.enable_pin	= AT91_PIN_PC28,
+	.partition_info	= nand_partitions,
+};
+
 static void __init kb9202_board_init(void)
 {
 	/* Serial */
@@ -111,6 +128,8 @@
 	at91_add_device_i2c();
 	/* SPI */
 	at91_add_device_spi(NULL, 0);
+	/* NAND */
+	at91_add_device_nand(&kb9202_nand_data);
 }
 
 MACHINE_START(KB9200, "KB920x")
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c
index edc2cc8..a43b061 100644
--- a/arch/arm/mach-at91rm9200/clock.c
+++ b/arch/arm/mach-at91rm9200/clock.c
@@ -29,7 +29,7 @@
 
 #include <asm/hardware.h>
 
-#include "generic.h"
+#include "clock.h"
 
 
 /*
@@ -38,23 +38,15 @@
  * PLLB be used at other rates (on boards that don't need USB), etc.
  */
 
-struct clk {
-	const char	*name;		/* unique clock name */
-	const char	*function;	/* function of the clock */
-	struct device	*dev;		/* device associated with function */
-	unsigned long	rate_hz;
-	struct clk	*parent;
-	u32		pmc_mask;
-	void		(*mode)(struct clk *, int);
-	unsigned	id:2;		/* PCK0..3, or 32k/main/a/b */
-	unsigned	primary:1;
-	unsigned	pll:1;
-	unsigned	programmable:1;
-	u16		users;
-};
+#define clk_is_primary(x)	((x)->type & CLK_TYPE_PRIMARY)
+#define clk_is_programmable(x)	((x)->type & CLK_TYPE_PROGRAMMABLE)
+#define clk_is_peripheral(x)	((x)->type & CLK_TYPE_PERIPHERAL)
 
-static spinlock_t	clk_lock;
-static u32		at91_pllb_usb_init;
+
+static LIST_HEAD(clocks);
+static DEFINE_SPINLOCK(clk_lock);
+
+static u32 at91_pllb_usb_init;
 
 /*
  * Four primary clock sources:  two crystal oscillators (32K, main), and
@@ -67,21 +59,20 @@
 	.rate_hz	= AT91_SLOW_CLOCK,
 	.users		= 1,		/* always on */
 	.id		= 0,
-	.primary	= 1,
+	.type		= CLK_TYPE_PRIMARY,
 };
 static struct clk main_clk = {
 	.name		= "main",
 	.pmc_mask	= AT91_PMC_MOSCS,	/* in PMC_SR */
 	.id		= 1,
-	.primary	= 1,
+	.type		= CLK_TYPE_PRIMARY,
 };
 static struct clk plla = {
 	.name		= "plla",
 	.parent		= &main_clk,
 	.pmc_mask	= AT91_PMC_LOCKA,	/* in PMC_SR */
 	.id		= 2,
-	.primary	= 1,
-	.pll		= 1,
+	.type		= CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
 };
 
 static void pllb_mode(struct clk *clk, int is_on)
@@ -94,6 +85,7 @@
 	} else
 		value = 0;
 
+	// REVISIT: Add work-around for AT91RM9200 Errata #26 ?
 	at91_sys_write(AT91_CKGR_PLLBR, value);
 
 	do {
@@ -107,8 +99,7 @@
 	.pmc_mask	= AT91_PMC_LOCKB,	/* in PMC_SR */
 	.mode		= pllb_mode,
 	.id		= 3,
-	.primary	= 1,
-	.pll		= 1,
+	.type		= CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
 };
 
 static void pmc_sys_mode(struct clk *clk, int is_on)
@@ -133,41 +124,6 @@
 	.mode		= pmc_sys_mode,
 };
 
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-/*
- * The four programmable clocks can be parented by any primary clock.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-	.name		= "pck0",
-	.pmc_mask	= AT91_PMC_PCK0,
-	.mode		= pmc_sys_mode,
-	.programmable	= 1,
-	.id		= 0,
-};
-static struct clk pck1 = {
-	.name		= "pck1",
-	.pmc_mask	= AT91_PMC_PCK1,
-	.mode		= pmc_sys_mode,
-	.programmable	= 1,
-	.id		= 1,
-};
-static struct clk pck2 = {
-	.name		= "pck2",
-	.pmc_mask	= AT91_PMC_PCK2,
-	.mode		= pmc_sys_mode,
-	.programmable	= 1,
-	.id		= 2,
-};
-static struct clk pck3 = {
-	.name		= "pck3",
-	.pmc_mask	= AT91_PMC_PCK3,
-	.mode		= pmc_sys_mode,
-	.programmable	= 1,
-	.id		= 3,
-};
-#endif	/* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
-
 
 /*
  * The master clock is divided from the CPU clock (by 1-4).  It's used for
@@ -187,131 +143,21 @@
 		at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
 }
 
-static struct clk udc_clk = {
-	.name		= "udc_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_UDP,
-	.mode		= pmc_periph_mode,
-};
-static struct clk ohci_clk = {
-	.name		= "ohci_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_UHP,
-	.mode		= pmc_periph_mode,
-};
-static struct clk ether_clk = {
-	.name		= "ether_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_EMAC,
-	.mode		= pmc_periph_mode,
-};
-static struct clk mmc_clk = {
-	.name		= "mci_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_MCI,
-	.mode		= pmc_periph_mode,
-};
-static struct clk twi_clk = {
-	.name		= "twi_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_TWI,
-	.mode		= pmc_periph_mode,
-};
-static struct clk usart0_clk = {
-	.name		= "usart0_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_US0,
-	.mode		= pmc_periph_mode,
-};
-static struct clk usart1_clk = {
-	.name		= "usart1_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_US1,
-	.mode		= pmc_periph_mode,
-};
-static struct clk usart2_clk = {
-	.name		= "usart2_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_US2,
-	.mode		= pmc_periph_mode,
-};
-static struct clk usart3_clk = {
-	.name		= "usart3_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_US3,
-	.mode		= pmc_periph_mode,
-};
-static struct clk spi_clk = {
-	.name		= "spi0_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_SPI,
-	.mode		= pmc_periph_mode,
-};
-static struct clk pioA_clk = {
-	.name		= "pioA_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_PIOA,
-	.mode		= pmc_periph_mode,
-};
-static struct clk pioB_clk = {
-	.name		= "pioB_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_PIOB,
-	.mode		= pmc_periph_mode,
-};
-static struct clk pioC_clk = {
-	.name		= "pioC_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_PIOC,
-	.mode		= pmc_periph_mode,
-};
-static struct clk pioD_clk = {
-	.name		= "pioD_clk",
-	.parent		= &mck,
-	.pmc_mask	= 1 << AT91_ID_PIOD,
-	.mode		= pmc_periph_mode,
-};
+static struct clk __init *at91_css_to_clk(unsigned long css)
+{
+	switch (css) {
+		case AT91_PMC_CSS_SLOW:
+			return &clk32k;
+		case AT91_PMC_CSS_MAIN:
+			return &main_clk;
+		case AT91_PMC_CSS_PLLA:
+			return &plla;
+		case AT91_PMC_CSS_PLLB:
+			return &pllb;
+	}
 
-static struct clk *const clock_list[] = {
-	/* four primary clocks -- MUST BE FIRST! */
-	&clk32k,
-	&main_clk,
-	&plla,
-	&pllb,
-
-	/* PLLB children (USB) */
-	&udpck,
-	&uhpck,
-
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-	/* programmable clocks */
-	&pck0,
-	&pck1,
-	&pck2,
-	&pck3,
-#endif	/* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
-
-	/* MCK and peripherals */
-	&mck,
-	&usart0_clk,
-	&usart1_clk,
-	&usart2_clk,
-	&usart3_clk,
-	&mmc_clk,
-	&udc_clk,
-	&twi_clk,
-	&spi_clk,
-	&pioA_clk,
-	&pioB_clk,
-	&pioC_clk,
-	&pioD_clk,
-	// ssc0..ssc2
-	// tc0..tc5
-	// irq0..irq6
-	&ohci_clk,
-	&ether_clk,
-};
-
+	return NULL;
+}
 
 /*
  * Associate a particular clock with a function (eg, "uart") and device.
@@ -329,14 +175,12 @@
 	clk->dev = dev;
 }
 
-/* clocks are all static for now; no refcounting necessary */
+/* clocks cannot be de-registered no refcounting necessary */
 struct clk *clk_get(struct device *dev, const char *id)
 {
-	int i;
+	struct clk *clk;
 
-	for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-		struct clk *clk = clock_list[i];
-
+	list_for_each_entry(clk, &clocks, node) {
 		if (strcmp(id, clk->name) == 0)
 			return clk;
 		if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
@@ -424,7 +268,7 @@
 	unsigned	prescale;
 	unsigned long	actual;
 
-	if (!clk->programmable)
+	if (!clk_is_programmable(clk))
 		return -EINVAL;
 	spin_lock_irqsave(&clk_lock, flags);
 
@@ -446,7 +290,7 @@
 	unsigned	prescale;
 	unsigned long	actual;
 
-	if (!clk->programmable)
+	if (!clk_is_programmable(clk))
 		return -EINVAL;
 	if (clk->users)
 		return -EBUSY;
@@ -484,7 +328,7 @@
 
 	if (clk->users)
 		return -EBUSY;
-	if (!parent->primary || !clk->programmable)
+	if (!clk_is_primary(parent) || !clk_is_programmable(clk))
 		return -EINVAL;
 	spin_lock_irqsave(&clk_lock, flags);
 
@@ -497,6 +341,18 @@
 }
 EXPORT_SYMBOL(clk_set_parent);
 
+/* establish PCK0..PCK3 parentage and rate */
+static void init_programmable_clock(struct clk *clk)
+{
+	struct clk	*parent;
+	u32		pckr;
+
+	pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+	parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
+	clk->parent = parent;
+	clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
+}
+
 #endif	/* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
 
 /*------------------------------------------------------------------------*/
@@ -506,6 +362,7 @@
 static int at91_clk_show(struct seq_file *s, void *unused)
 {
 	u32		scsr, pcsr, sr;
+	struct clk	*clk;
 	unsigned	i;
 
 	seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
@@ -523,9 +380,8 @@
 
 	seq_printf(s, "\n");
 
-	for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-		char		*state;
-		struct clk	*clk = clock_list[i];
+	list_for_each_entry(clk, &clocks, node) {
+		char	*state;
 
 		if (clk->mode == pmc_sys_mode)
 			state = (scsr & clk->pmc_mask) ? "on" : "off";
@@ -570,6 +426,28 @@
 
 /*------------------------------------------------------------------------*/
 
+/* Register a new clock */
+int __init clk_register(struct clk *clk)
+{
+	if (clk_is_peripheral(clk)) {
+		clk->parent = &mck;
+		clk->mode = pmc_periph_mode;
+		list_add_tail(&clk->node, &clocks);
+	}
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+	else if (clk_is_programmable(clk)) {
+		clk->mode = pmc_sys_mode;
+		init_programmable_clock(clk);
+		list_add_tail(&clk->node, &clocks);
+	}
+#endif
+
+	return 0;
+}
+
+
+/*------------------------------------------------------------------------*/
+
 static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
 {
 	unsigned mul, div;
@@ -640,20 +518,17 @@
 	return 0;
 }
 
-
 /*
  * Several unused clocks may be active.  Turn them off.
  */
-static void at91_periphclk_reset(void)
+static void __init at91_periphclk_reset(void)
 {
 	unsigned long reg;
-	int i;
+	struct clk *clk;
 
 	reg = at91_sys_read(AT91_PMC_PCSR);
 
-	for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-		struct clk	*clk = clock_list[i];
-
+	list_for_each_entry(clk, &clocks, node) {
 		if (clk->mode != pmc_periph_mode)
 			continue;
 
@@ -664,11 +539,25 @@
 	at91_sys_write(AT91_PMC_PCDR, reg);
 }
 
+static struct clk *const standard_pmc_clocks[] __initdata = {
+	/* four primary clocks */
+	&clk32k,
+	&main_clk,
+	&plla,
+	&pllb,
+
+	/* PLLB children (USB) */
+	&udpck,
+	&uhpck,
+
+	/* MCK */
+	&mck
+};
+
 int __init at91_clock_init(unsigned long main_clock)
 {
 	unsigned tmp, freq, mckr;
-
-	spin_lock_init(&clk_lock);
+	int i;
 
 	/*
 	 * When the bootloader initialized the main oscillator correctly,
@@ -709,11 +598,15 @@
 	 * For now, assume this parentage won't change.
 	 */
 	mckr = at91_sys_read(AT91_PMC_MCKR);
-	mck.parent = clock_list[mckr & AT91_PMC_CSS];
+	mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
 	freq = mck.parent->rate_hz;
 	freq /= (1 << ((mckr >> 2) & 3));		/* prescale */
 	mck.rate_hz = freq / (1 + ((mckr >> 8) & 3));	/* mdiv */
 
+	/* Register the PMC's standard clocks */
+	for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
+		list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
+
 	/* MCK and CPU clock are "always on" */
 	clk_enable(&mck);
 
@@ -722,35 +615,8 @@
 		(unsigned) main_clock / 1000000,
 		((unsigned) main_clock % 1000000) / 1000);
 
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-	/* establish PCK0..PCK3 parentage */
-	for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) {
-		struct clk	*clk = clock_list[tmp], *parent;
-		u32		pckr;
-
-		if (!clk->programmable)
-			continue;
-
-		pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
-		parent = clock_list[pckr & AT91_PMC_CSS];
-		clk->parent = parent;
-		clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
-
-		if (clk->users == 0) {
-			/* not being used, so switch it off */
-			at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
-		}
-	}
-#else
 	/* disable all programmable clocks */
 	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
-#endif
-
-	/* enable the PIO clocks */
-	clk_enable(&pioA_clk);
-	clk_enable(&pioB_clk);
-	clk_enable(&pioC_clk);
-	clk_enable(&pioD_clk);
 
 	/* disable all other unused peripheral clocks */
 	at91_periphclk_reset();
diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91rm9200/clock.h
new file mode 100644
index 0000000..0592e66
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/clock.h
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/clock.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define CLK_TYPE_PRIMARY	0x1
+#define CLK_TYPE_PLL		0x2
+#define CLK_TYPE_PROGRAMMABLE	0x4
+#define CLK_TYPE_PERIPHERAL	0x8
+
+
+struct clk {
+	struct list_head node;
+	const char	*name;		/* unique clock name */
+	const char	*function;	/* function of the clock */
+	struct device	*dev;		/* device associated with function */
+	unsigned long	rate_hz;
+	struct clk	*parent;
+	u32		pmc_mask;
+	void		(*mode)(struct clk *, int);
+	unsigned	id:2;		/* PCK0..3, or 32k/main/a/b */
+	unsigned	type;		/* clock type */
+	u16		users;
+};
+
+
+extern int __init clk_register(struct clk *clk);
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index 4352acb..0152553 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -35,13 +35,13 @@
 
 static struct resource at91_usbh_resources[] = {
 	[0] = {
-		.start	= AT91_UHP_BASE,
-		.end	= AT91_UHP_BASE + SZ_1M - 1,
+		.start	= AT91RM9200_UHP_BASE,
+		.end	= AT91RM9200_UHP_BASE + SZ_1M - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_UHP,
-		.end	= AT91_ID_UHP,
+		.start	= AT91RM9200_ID_UHP,
+		.end	= AT91RM9200_ID_UHP,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -80,13 +80,13 @@
 
 static struct resource at91_udc_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_UDP,
-		.end	= AT91_BASE_UDP + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_UDP,
+		.end	= AT91RM9200_BASE_UDP + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_UDP,
-		.end	= AT91_ID_UDP,
+		.start	= AT91RM9200_ID_UDP,
+		.end	= AT91RM9200_ID_UDP,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -131,13 +131,13 @@
 
 static struct resource at91_eth_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_EMAC,
-		.end	= AT91_BASE_EMAC + SZ_16K - 1,
+		.start	= AT91_VA_BASE_EMAC,
+		.end	= AT91_VA_BASE_EMAC + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_EMAC,
-		.end	= AT91_ID_EMAC,
+		.start	= AT91RM9200_ID_EMAC,
+		.end	= AT91RM9200_ID_EMAC,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -263,13 +263,13 @@
 
 static struct resource at91_mmc_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_MCI,
-		.end	= AT91_BASE_MCI + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_MCI,
+		.end	= AT91RM9200_BASE_MCI + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_MCI,
-		.end	= AT91_ID_MCI,
+		.start	= AT91RM9200_ID_MCI,
+		.end	= AT91RM9200_ID_MCI,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -423,13 +423,13 @@
 
 static struct resource at91_spi_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_SPI,
-		.end	= AT91_BASE_SPI + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_SPI,
+		.end	= AT91RM9200_BASE_SPI + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_SPI,
-		.end	= AT91_ID_SPI,
+		.start	= AT91RM9200_ID_SPI,
+		.end	= AT91RM9200_ID_SPI,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -582,13 +582,13 @@
 
 static struct resource uart0_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_US0,
-		.end	= AT91_BASE_US0 + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_US0,
+		.end	= AT91RM9200_BASE_US0 + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_US0,
-		.end	= AT91_ID_US0,
+		.start	= AT91RM9200_ID_US0,
+		.end	= AT91RM9200_ID_US0,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -624,13 +624,13 @@
 
 static struct resource uart1_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_US1,
-		.end	= AT91_BASE_US1 + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_US1,
+		.end	= AT91RM9200_BASE_US1 + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_US1,
-		.end	= AT91_ID_US1,
+		.start	= AT91RM9200_ID_US1,
+		.end	= AT91RM9200_ID_US1,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -665,13 +665,13 @@
 
 static struct resource uart2_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_US2,
-		.end	= AT91_BASE_US2 + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_US2,
+		.end	= AT91RM9200_BASE_US2 + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_US2,
-		.end	= AT91_ID_US2,
+		.start	= AT91RM9200_ID_US2,
+		.end	= AT91RM9200_ID_US2,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -700,13 +700,13 @@
 
 static struct resource uart3_resources[] = {
 	[0] = {
-		.start	= AT91_BASE_US3,
-		.end	= AT91_BASE_US3 + SZ_16K - 1,
+		.start	= AT91RM9200_BASE_US3,
+		.end	= AT91RM9200_BASE_US3 + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= AT91_ID_US3,
-		.end	= AT91_ID_US3,
+		.start	= AT91RM9200_ID_US3,
+		.end	= AT91RM9200_ID_US3,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h
index 7979d8a..694e411 100644
--- a/arch/arm/mach-at91rm9200/generic.h
+++ b/arch/arm/mach-at91rm9200/generic.h
@@ -8,18 +8,17 @@
  * published by the Free Software Foundation.
  */
 
+ /* Processors */
+extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
+
  /* Interrupts */
-extern void __init at91rm9200_init_irq(unsigned int priority[]);
+extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
 extern void __init at91_aic_init(unsigned int priority[]);
-extern void __init at91_gpio_irq_setup(unsigned banks);
 
  /* Timer */
 struct sys_timer;
 extern struct sys_timer at91rm9200_timer;
 
- /* Memory Map */
-extern void __init at91rm9200_map_io(void);
-
  /* Clocks */
 extern int __init at91_clock_init(unsigned long main_clock);
 struct device;
@@ -29,3 +28,14 @@
 extern void at91_irq_suspend(void);
 extern void at91_irq_resume(void);
 
+ /* GPIO */
+#define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */
+#define AT91RM9200_BGA		4	/* AT91RM9200 BGA package has 4 banks */
+
+struct at91_gpio_bank {
+	unsigned short id;		/* peripheral ID */
+	unsigned long offset;		/* offset from system peripheral base */
+	struct clk *clock;		/* associated clock */
+};
+extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
+extern void __init at91_gpio_irq_setup(void);
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index cec199f..58c9bf5 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -9,6 +9,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -20,12 +21,12 @@
 #include <asm/hardware.h>
 #include <asm/arch/gpio.h>
 
-static const u32 pio_controller_offset[4] = {
-	AT91_PIOA,
-	AT91_PIOB,
-	AT91_PIOC,
-	AT91_PIOD,
-};
+#include "generic.h"
+
+
+static struct at91_gpio_bank *gpio;
+static int gpio_banks;
+
 
 static inline void __iomem *pin_to_controller(unsigned pin)
 {
@@ -33,8 +34,8 @@
 
 	pin -= PIN_BASE;
 	pin /= 32;
-	if (likely(pin < BGA_GPIO_BANKS))
-		return sys_base + pio_controller_offset[pin];
+	if (likely(pin < gpio_banks))
+		return sys_base + gpio[pin].offset;
 
 	return NULL;
 }
@@ -179,7 +180,6 @@
 
 /*--------------------------------------------------------------------------*/
 
-
 /*
  * assuming the pin is muxed as a gpio output, set its value.
  */
@@ -216,8 +216,8 @@
 
 #ifdef CONFIG_PM
 
-static u32 wakeups[BGA_GPIO_BANKS];
-static u32 backups[BGA_GPIO_BANKS];
+static u32 wakeups[MAX_GPIO_BANKS];
+static u32 backups[MAX_GPIO_BANKS];
 
 static int gpio_irq_set_wake(unsigned pin, unsigned state)
 {
@@ -226,7 +226,7 @@
 	pin -= PIN_BASE;
 	pin /= 32;
 
-	if (unlikely(pin >= BGA_GPIO_BANKS))
+	if (unlikely(pin >= MAX_GPIO_BANKS))
 		return -EINVAL;
 
 	if (state)
@@ -241,8 +241,8 @@
 {
 	int i;
 
-	for (i = 0; i < BGA_GPIO_BANKS; i++) {
-		u32 pio = pio_controller_offset[i];
+	for (i = 0; i < gpio_banks; i++) {
+		u32 pio = gpio[i].offset;
 
 		/*
 		 * Note: drivers should have disabled GPIO interrupts that
@@ -257,14 +257,14 @@
 		 * first place!
 		 */
 		backups[i] = at91_sys_read(pio + PIO_IMR);
-		at91_sys_write(pio_controller_offset[i] + PIO_IDR, backups[i]);
-		at91_sys_write(pio_controller_offset[i] + PIO_IER, wakeups[i]);
+		at91_sys_write(pio + PIO_IDR, backups[i]);
+		at91_sys_write(pio + PIO_IER, wakeups[i]);
 
 		if (!wakeups[i]) {
-			disable_irq_wake(AT91_ID_PIOA + i);
-			at91_sys_write(AT91_PMC_PCDR, 1 << (AT91_ID_PIOA + i));
+			disable_irq_wake(gpio[i].id);
+			at91_sys_write(AT91_PMC_PCDR, 1 << gpio[i].id);
 		} else {
-			enable_irq_wake(AT91_ID_PIOA + i);
+			enable_irq_wake(gpio[i].id);
 #ifdef CONFIG_PM_DEBUG
 			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]);
 #endif
@@ -276,16 +276,13 @@
 {
 	int i;
 
-	for (i = 0; i < BGA_GPIO_BANKS; i++) {
-		at91_sys_write(pio_controller_offset[i] + PIO_IDR, wakeups[i]);
-		at91_sys_write(pio_controller_offset[i] + PIO_IER, backups[i]);
-	}
+	for (i = 0; i < gpio_banks; i++) {
+		u32 pio = gpio[i].offset;
 
-	at91_sys_write(AT91_PMC_PCER,
-			  (1 << AT91_ID_PIOA)
-			| (1 << AT91_ID_PIOB)
-			| (1 << AT91_ID_PIOC)
-			| (1 << AT91_ID_PIOD));
+		at91_sys_write(pio + PIO_IDR, wakeups[i]);
+		at91_sys_write(pio + PIO_IER, backups[i]);
+		at91_sys_write(AT91_PMC_PCER, 1 << gpio[i].id);
+	}
 }
 
 #else
@@ -377,20 +374,25 @@
 	/* now it may re-trigger */
 }
 
-/* call this from board-specific init_irq */
-void __init at91_gpio_irq_setup(unsigned banks)
-{
-	unsigned	pioc, pin, id;
+/*--------------------------------------------------------------------------*/
 
-	if (banks > 4)
-		banks = 4;
-	for (pioc = 0, pin = PIN_BASE, id = AT91_ID_PIOA;
-			pioc < banks;
-			pioc++, id++) {
+/*
+ * Called from the processor-specific init to enable GPIO interrupt support.
+ */
+void __init at91_gpio_irq_setup(void)
+{
+	unsigned	pioc, pin;
+
+	for (pioc = 0, pin = PIN_BASE;
+			pioc < gpio_banks;
+			pioc++) {
 		void __iomem	*controller;
+		unsigned	id = gpio[pioc].id;
 		unsigned	i;
 
-		controller = (void __iomem *) AT91_VA_BASE_SYS + pio_controller_offset[pioc];
+		clk_enable(gpio[pioc].clock);	/* enable PIO controller's clock */
+
+		controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
 		__raw_writel(~0, controller + PIO_IDR);
 
 		set_irq_data(id, (void *) pin);
@@ -408,5 +410,16 @@
 
 		set_irq_chained_handler(id, gpio_irq_handler);
 	}
-	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks);
+	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
+}
+
+/*
+ * Called from the processor-specific init to enable GPIO pin support.
+ */
+void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
+{
+	BUG_ON(nr_banks > MAX_GPIO_BANKS);
+
+	gpio = data;
+	gpio_banks = nr_banks;
 }
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c
index c3a5e77..3e48811 100644
--- a/arch/arm/mach-at91rm9200/irq.c
+++ b/arch/arm/mach-at91rm9200/irq.c
@@ -34,8 +34,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
-#include "generic.h"
-
 
 static void at91_aic_mask_irq(unsigned int irq)
 {
@@ -61,12 +59,12 @@
 		srctype = AT91_AIC_SRCTYPE_RISING;
 		break;
 	case IRQT_LOW:
-		if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))	/* only supported on external interrupts */
+		if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0))	/* only supported on external interrupts */
 			return -EINVAL;
 		srctype = AT91_AIC_SRCTYPE_LOW;
 		break;
 	case IRQT_FALLING:
-		if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))	/* only supported on external interrupts */
+		if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0))	/* only supported on external interrupts */
 			return -EINVAL;
 		srctype = AT91_AIC_SRCTYPE_FALLING;
 		break;
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c
index 47e5480..32c95d8 100644
--- a/arch/arm/mach-at91rm9200/pm.c
+++ b/arch/arm/mach-at91rm9200/pm.c
@@ -123,13 +123,13 @@
 			(at91_sys_read(AT91_PMC_PCSR)
 					| (1 << AT91_ID_FIQ)
 					| (1 << AT91_ID_SYS)
-					| (1 << AT91_ID_IRQ0)
-					| (1 << AT91_ID_IRQ1)
-					| (1 << AT91_ID_IRQ2)
-					| (1 << AT91_ID_IRQ3)
-					| (1 << AT91_ID_IRQ4)
-					| (1 << AT91_ID_IRQ5)
-					| (1 << AT91_ID_IRQ6))
+					| (1 << AT91RM9200_ID_IRQ0)
+					| (1 << AT91RM9200_ID_IRQ1)
+					| (1 << AT91RM9200_ID_IRQ2)
+					| (1 << AT91RM9200_ID_IRQ3)
+					| (1 << AT91RM9200_ID_IRQ4)
+					| (1 << AT91RM9200_ID_IRQ5)
+					| (1 << AT91RM9200_ID_IRQ6))
 				& at91_sys_read(AT91_AIC_IMR),
 			state);
 
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index f1b7400..e346b03 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -15,6 +15,12 @@
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9302 Evaluation Board.
 
+config MACH_EDB9312
+	bool "Support Cirrus Logic EDB9312"
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9312 Evaluation Board.
+
 config MACH_EDB9315
 	bool "Support Cirrus Logic EDB9315"
 	help
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 1f5a6b0..c2eb18b 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -7,6 +7,7 @@
 obj-			:=
 
 obj-$(CONFIG_MACH_EDB9302)	+= edb9302.o
+obj-$(CONFIG_MACH_EDB9312)	+= edb9312.o
 obj-$(CONFIG_MACH_EDB9315)	+= edb9315.o
 obj-$(CONFIG_MACH_EDB9315A)	+= edb9315a.o
 obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o
diff --git a/arch/arm/mach-ep93xx/edb9312.c b/arch/arm/mach-ep93xx/edb9312.c
new file mode 100644
index 0000000..9e39921
--- /dev/null
+++ b/arch/arm/mach-ep93xx/edb9312.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arm/mach-ep93xx/edb9312.c
+ * Cirrus Logic EDB9312 support.
+ *
+ * Copyright (C) 2006 Infosys Technologies Limited
+ * 	Toufeeq Hussain	<toufeeq_hussain@infosys.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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb9312_flash_data = {
+	.width		= 4,
+};
+
+static struct resource edb9312_flash_resource = {
+	.start		= 0x60000000,
+	.end		= 0x61ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device edb9312_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &edb9312_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &edb9312_flash_resource,
+};
+
+static void __init edb9312_init_machine(void)
+{
+	ep93xx_init_devices();
+	platform_device_register(&edb9312_flash);
+}
+
+MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
+	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb9312_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 823e25d..a1ae49d 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -69,16 +69,16 @@
 	if (addr)
 		switch (size) {
 		case 1:
-			asm("ldr%?b	%0, [%1, %2]"
-				: "=r" (v) : "r" (addr), "r" (where));
+			asm("ldrb	%0, [%1, %2]"
+				: "=r" (v) : "r" (addr), "r" (where) : "cc");
 			break;
 		case 2:
-			asm("ldr%?h	%0, [%1, %2]"
-				: "=r" (v) : "r" (addr), "r" (where));
+			asm("ldrh	%0, [%1, %2]"
+				: "=r" (v) : "r" (addr), "r" (where) : "cc");
 			break;
 		case 4:
-			asm("ldr%?	%0, [%1, %2]"
-				: "=r" (v) : "r" (addr), "r" (where));
+			asm("ldr	%0, [%1, %2]"
+				: "=r" (v) : "r" (addr), "r" (where) : "cc");
 			break;
 		}
 
@@ -103,16 +103,19 @@
 	if (addr)
 		switch (size) {
 		case 1:
-			asm("str%?b	%0, [%1, %2]"
-				: : "r" (value), "r" (addr), "r" (where));
+			asm("strb	%0, [%1, %2]"
+				: : "r" (value), "r" (addr), "r" (where)
+				: "cc");
 			break;
 		case 2:
-			asm("str%?h	%0, [%1, %2]"
-				: : "r" (value), "r" (addr), "r" (where));
+			asm("strh	%0, [%1, %2]"
+				: : "r" (value), "r" (addr), "r" (where)
+				: "cc");
 			break;
 		case 4:
-			asm("str%?	%0, [%1, %2]"
-				: : "r" (value), "r" (addr), "r" (where));
+			asm("str	%0, [%1, %2]"
+				: : "r" (value), "r" (addr), "r" (where)
+				: "cc");
 			break;
 		}
 
diff --git a/arch/arm/mach-iop32x/Kconfig b/arch/arm/mach-iop32x/Kconfig
new file mode 100644
index 0000000..c072d94
--- /dev/null
+++ b/arch/arm/mach-iop32x/Kconfig
@@ -0,0 +1,35 @@
+if ARCH_IOP32X
+
+menu "IOP32x Implementation Options"
+
+comment "IOP32x Platform Types"
+
+config MACH_GLANTANK
+	bool "Enable support for the IO-Data GLAN Tank"
+	help
+	  Say Y here if you want to run your kernel on the GLAN Tank
+	  NAS appliance or machines from IO-Data's HDL-Gxxx, HDL-GWxxx
+	  and HDL-GZxxx series.
+
+config ARCH_IQ80321
+	bool "Enable support for IQ80321"
+	help
+	  Say Y here if you want to run your kernel on the Intel IQ80321
+	  evaluation kit for the IOP321 processor.
+
+config ARCH_IQ31244
+	bool "Enable support for EP80219/IQ31244"
+	help
+	  Say Y here if you want to run your kernel on the Intel EP80219
+	  evaluation kit for the Intel 80219 processor (a IOP321 variant)
+	  or the IQ31244 evaluation kit for the IOP321 processor.
+
+config MACH_N2100
+	bool "Enable support for the Thecus n2100"
+	help
+	  Say Y here if you want to run your kernel on the Thecus n2100
+	  NAS appliance.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-iop32x/Makefile b/arch/arm/mach-iop32x/Makefile
new file mode 100644
index 0000000..7b05b37
--- /dev/null
+++ b/arch/arm/mach-iop32x/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y			:= irq.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+obj-$(CONFIG_MACH_GLANTANK) += glantank.o
+obj-$(CONFIG_ARCH_IQ80321) += iq80321.o
+obj-$(CONFIG_ARCH_IQ31244) += iq31244.o
+obj-$(CONFIG_MACH_N2100) += n2100.o
diff --git a/arch/arm/mach-iop32x/Makefile.boot b/arch/arm/mach-iop32x/Makefile.boot
new file mode 100644
index 0000000..47000dc
--- /dev/null
+++ b/arch/arm/mach-iop32x/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0xa0008000
+params_phys-y	:= 0xa0000100
+initrd_phys-y	:= 0xa0800000
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
new file mode 100644
index 0000000..b9b7650
--- /dev/null
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -0,0 +1,195 @@
+/*
+ * arch/arm/mach-iop32x/glantank.c
+ *
+ * Board support code for the GLAN Tank.
+ *
+ * Copyright (C) 2006 Martin Michlmayr <tbm@cyrius.com>
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+
+/*
+ * GLAN Tank timer tick configuration.
+ */
+static void __init glantank_timer_init(void)
+{
+	/* 33.333 MHz crystal.  */
+	iop3xx_init_time(200000000);
+}
+
+static struct sys_timer glantank_timer = {
+	.init		= glantank_timer_init,
+	.offset		= iop3xx_gettimeoffset,
+};
+
+
+/*
+ * GLAN Tank I/O.
+ */
+static struct map_desc glantank_io_desc[] __initdata = {
+	{	/* on-board devices */
+		.virtual	= GLANTANK_UART,
+		.pfn		= __phys_to_pfn(GLANTANK_UART),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init glantank_map_io(void)
+{
+	iop3xx_map_io();
+	iotable_init(glantank_io_desc, ARRAY_SIZE(glantank_io_desc));
+}
+
+
+/*
+ * GLAN Tank PCI.
+ */
+#define INTA	IRQ_IOP32X_XINT0
+#define INTB	IRQ_IOP32X_XINT1
+#define INTC	IRQ_IOP32X_XINT2
+#define INTD	IRQ_IOP32X_XINT3
+
+static inline int __init
+glantank_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 * A       B       C       D
+		 */
+		{INTD, INTD, INTD, INTD}, /* UART (8250) */
+		{INTA, INTA, INTA, INTA}, /* Ethernet (E1000) */
+		{INTB, INTB, INTB, INTB}, /* IDE (AEC6280R) */
+		{INTC, INTC, INTC, INTC}, /* USB (NEC) */
+	};
+
+	BUG_ON(pin < 1 || pin > 4);
+
+	return pci_irq_table[slot % 4][pin - 1];
+}
+
+static struct hw_pci glantank_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iop3xx_pci_setup,
+	.preinit	= iop3xx_pci_preinit,
+	.scan		= iop3xx_pci_scan_bus,
+	.map_irq	= glantank_pci_map_irq,
+};
+
+static int __init glantank_pci_init(void)
+{
+	if (machine_is_glantank())
+		pci_common_init(&glantank_pci);
+
+	return 0;
+}
+
+subsys_initcall(glantank_pci_init);
+
+
+/*
+ * GLAN Tank machine initialization.
+ */
+static struct physmap_flash_data glantank_flash_data = {
+	.width		= 1,
+};
+
+static struct resource glantank_flash_resource = {
+	.start		= 0xf0000000,
+	.end		= 0xf007ffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device glantank_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &glantank_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &glantank_flash_resource,
+};
+
+static struct plat_serial8250_port glantank_serial_port[] = {
+	{
+		.mapbase	= GLANTANK_UART,
+		.membase	= (char *)GLANTANK_UART,
+		.irq		= IRQ_IOP32X_XINT3,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 0,
+		.uartclk	= 1843200,
+	},
+	{ },
+};
+
+static struct resource glantank_uart_resource = {
+	.start		= GLANTANK_UART,
+	.end		= GLANTANK_UART + 7,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device glantank_serial_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev		= {
+		.platform_data		= glantank_serial_port,
+	},
+	.num_resources	= 1,
+	.resource	= &glantank_uart_resource,
+};
+
+static void glantank_power_off(void)
+{
+	__raw_writeb(0x01, 0xfe8d0004);
+
+	while (1)
+		;
+}
+
+static void __init glantank_init_machine(void)
+{
+	platform_device_register(&iop3xx_i2c0_device);
+	platform_device_register(&iop3xx_i2c1_device);
+	platform_device_register(&glantank_flash_device);
+	platform_device_register(&glantank_serial_device);
+
+	pm_power_off = glantank_power_off;
+}
+
+MACHINE_START(GLANTANK, "GLAN Tank")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= GLANTANK_UART,
+	.io_pg_offst	= ((GLANTANK_UART) >> 18) & 0xfffc,
+	.boot_params	= 0xa0000100,
+	.map_io		= glantank_map_io,
+	.init_irq	= iop32x_init_irq,
+	.timer		= &glantank_timer,
+	.init_machine	= glantank_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
new file mode 100644
index 0000000..be4aedf
--- /dev/null
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -0,0 +1,293 @@
+/*
+ * arch/arm/mach-iop32x/iq31244.c
+ *
+ * Board support code for the Intel EP80219 and IQ31244 platforms.
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright 2003 (c) MontaVista, Software, Inc.
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+
+/*
+ * The EP80219 and IQ31244 use the same machine ID.  To find out
+ * which of the two we're running on, we look at the processor ID.
+ */
+static int is_80219(void)
+{
+	extern int processor_id;
+	return !!((processor_id & 0xffffffe0) == 0x69052e20);
+}
+
+
+/*
+ * EP80219/IQ31244 timer tick configuration.
+ */
+static void __init iq31244_timer_init(void)
+{
+	if (is_80219()) {
+		/* 33.333 MHz crystal.  */
+		iop3xx_init_time(200000000);
+	} else {
+		/* 33.000 MHz crystal.  */
+		iop3xx_init_time(198000000);
+	}
+}
+
+static struct sys_timer iq31244_timer = {
+	.init		= iq31244_timer_init,
+	.offset		= iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ31244 I/O.
+ */
+static struct map_desc iq31244_io_desc[] __initdata = {
+	{	/* on-board devices */
+		.virtual	= IQ31244_UART,
+		.pfn		= __phys_to_pfn(IQ31244_UART),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init iq31244_map_io(void)
+{
+	iop3xx_map_io();
+	iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
+}
+
+
+/*
+ * EP80219/IQ31244 PCI.
+ */
+static inline int __init
+ep80219_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (slot == 0) {
+		/* CFlash */
+		irq = IRQ_IOP32X_XINT1;
+	} else if (slot == 1) {
+		/* 82551 Pro 100 */
+		irq = IRQ_IOP32X_XINT0;
+	} else if (slot == 2) {
+		/* PCI-X Slot */
+		irq = IRQ_IOP32X_XINT3;
+	} else if (slot == 3) {
+		/* SATA */
+		irq = IRQ_IOP32X_XINT2;
+	} else {
+		printk(KERN_ERR "ep80219_pci_map_irq() called for unknown "
+			"device PCI:%d:%d:%d\n", dev->bus->number,
+			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		irq = -1;
+	}
+
+	return irq;
+}
+
+static struct hw_pci ep80219_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iop3xx_pci_setup,
+	.preinit	= iop3xx_pci_preinit,
+	.scan		= iop3xx_pci_scan_bus,
+	.map_irq	= ep80219_pci_map_irq,
+};
+
+static inline int __init
+iq31244_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (slot == 0) {
+		/* CFlash */
+		irq = IRQ_IOP32X_XINT1;
+	} else if (slot == 1) {
+		/* SATA */
+		irq = IRQ_IOP32X_XINT2;
+	} else if (slot == 2) {
+		/* PCI-X Slot */
+		irq = IRQ_IOP32X_XINT3;
+	} else if (slot == 3) {
+		/* 82546 GigE */
+		irq = IRQ_IOP32X_XINT0;
+	} else {
+		printk(KERN_ERR "iq31244_pci_map_irq called for unknown "
+			"device PCI:%d:%d:%d\n", dev->bus->number,
+			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		irq = -1;
+	}
+
+	return irq;
+}
+
+static struct hw_pci iq31244_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iop3xx_pci_setup,
+	.preinit	= iop3xx_pci_preinit,
+	.scan		= iop3xx_pci_scan_bus,
+	.map_irq	= iq31244_pci_map_irq,
+};
+
+static int __init iq31244_pci_init(void)
+{
+	if (machine_is_iq31244()) {
+		if (is_80219()) {
+			pci_common_init(&ep80219_pci);
+		} else {
+			pci_common_init(&iq31244_pci);
+		}
+	}
+
+	return 0;
+}
+
+subsys_initcall(iq31244_pci_init);
+
+
+/*
+ * IQ31244 machine initialisation.
+ */
+static struct physmap_flash_data iq31244_flash_data = {
+	.width		= 2,
+};
+
+static struct resource iq31244_flash_resource = {
+	.start		= 0xf0000000,
+	.end		= 0xf07fffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device iq31244_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &iq31244_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &iq31244_flash_resource,
+};
+
+static struct plat_serial8250_port iq31244_serial_port[] = {
+	{
+		.mapbase	= IQ31244_UART,
+		.membase	= (char *)IQ31244_UART,
+		.irq		= IRQ_IOP32X_XINT1,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 0,
+		.uartclk	= 1843200,
+	},
+	{ },
+};
+
+static struct resource iq31244_uart_resource = {
+	.start		= IQ31244_UART,
+	.end		= IQ31244_UART + 7,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device iq31244_serial_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev		= {
+		.platform_data		= iq31244_serial_port,
+	},
+	.num_resources	= 1,
+	.resource	= &iq31244_uart_resource,
+};
+
+/*
+ * This function will send a SHUTDOWN_COMPLETE message to the PIC
+ * controller over I2C.  We are not using the i2c subsystem since
+ * we are going to power off and it may be removed
+ */
+void ep80219_power_off(void)
+{
+	/*
+	 * Send the Address byte w/ the start condition
+	 */
+	*IOP3XX_IDBR1 = 0x60;
+	*IOP3XX_ICR1 = 0xE9;
+	mdelay(1);
+
+	/*
+	 * Send the START_MSG byte w/ no start or stop condition
+	 */
+	*IOP3XX_IDBR1 = 0x0F;
+	*IOP3XX_ICR1 = 0xE8;
+	mdelay(1);
+
+	/*
+	 * Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or
+	 * stop condition
+	 */
+	*IOP3XX_IDBR1 = 0x03;
+	*IOP3XX_ICR1 = 0xE8;
+	mdelay(1);
+
+	/*
+	 * Send an ignored byte w/ stop condition
+	 */
+	*IOP3XX_IDBR1 = 0x00;
+	*IOP3XX_ICR1 = 0xEA;
+
+	while (1)
+		;
+}
+
+static void __init iq31244_init_machine(void)
+{
+	platform_device_register(&iop3xx_i2c0_device);
+	platform_device_register(&iop3xx_i2c1_device);
+	platform_device_register(&iq31244_flash_device);
+	platform_device_register(&iq31244_serial_device);
+
+	if (is_80219())
+		pm_power_off = ep80219_power_off;
+}
+
+MACHINE_START(IQ31244, "Intel IQ31244")
+	/* Maintainer: Intel Corp. */
+	.phys_io	= IQ31244_UART,
+	.io_pg_offst	= ((IQ31244_UART) >> 18) & 0xfffc,
+	.boot_params	= 0xa0000100,
+	.map_io		= iq31244_map_io,
+	.init_irq	= iop32x_init_irq,
+	.timer		= &iq31244_timer,
+	.init_machine	= iq31244_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
new file mode 100644
index 0000000..1f37b55
--- /dev/null
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -0,0 +1,193 @@
+/*
+ * arch/arm/mach-iop32x/iq80321.c
+ *
+ * Board support code for the Intel IQ80321 platform.
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * IQ80321 timer tick configuration.
+ */
+static void __init iq80321_timer_init(void)
+{
+	/* 33.333 MHz crystal.  */
+	iop3xx_init_time(200000000);
+}
+
+static struct sys_timer iq80321_timer = {
+	.init		= iq80321_timer_init,
+	.offset		= iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ80321 I/O.
+ */
+static struct map_desc iq80321_io_desc[] __initdata = {
+ 	{	/* on-board devices */
+		.virtual	= IQ80321_UART,
+		.pfn		= __phys_to_pfn(IQ80321_UART),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init iq80321_map_io(void)
+{
+	iop3xx_map_io();
+	iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
+}
+
+
+/*
+ * IQ80321 PCI.
+ */
+static inline int __init
+iq80321_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if ((slot == 2 || slot == 6) && pin == 1) {
+		/* PCI-X Slot INTA */
+		irq = IRQ_IOP32X_XINT2;
+	} else if ((slot == 2 || slot == 6) && pin == 2) {
+		/* PCI-X Slot INTA */
+		irq = IRQ_IOP32X_XINT3;
+	} else if ((slot == 2 || slot == 6) && pin == 3) {
+		/* PCI-X Slot INTA */
+		irq = IRQ_IOP32X_XINT0;
+	} else if ((slot == 2 || slot == 6) && pin == 4) {
+		/* PCI-X Slot INTA */
+		irq = IRQ_IOP32X_XINT1;
+	} else if (slot == 4 || slot == 8) {
+		/* Gig-E */
+		irq = IRQ_IOP32X_XINT0;
+	} else {
+		printk(KERN_ERR "iq80321_pci_map_irq() called for unknown "
+			"device PCI:%d:%d:%d\n", dev->bus->number,
+			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		irq = -1;
+	}
+
+	return irq;
+}
+
+static struct hw_pci iq80321_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iop3xx_pci_setup,
+	.preinit	= iop3xx_pci_preinit,
+	.scan		= iop3xx_pci_scan_bus,
+	.map_irq	= iq80321_pci_map_irq,
+};
+
+static int __init iq80321_pci_init(void)
+{
+	if (machine_is_iq80321())
+		pci_common_init(&iq80321_pci);
+
+	return 0;
+}
+
+subsys_initcall(iq80321_pci_init);
+
+
+/*
+ * IQ80321 machine initialisation.
+ */
+static struct physmap_flash_data iq80321_flash_data = {
+	.width		= 1,
+};
+
+static struct resource iq80321_flash_resource = {
+	.start		= 0xf0000000,
+	.end		= 0xf07fffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device iq80321_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &iq80321_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &iq80321_flash_resource,
+};
+
+static struct plat_serial8250_port iq80321_serial_port[] = {
+	{
+		.mapbase	= IQ80321_UART,
+		.membase	= (char *)IQ80321_UART,
+		.irq		= IRQ_IOP32X_XINT1,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 0,
+		.uartclk	= 1843200,
+	},
+	{ },
+};
+
+static struct resource iq80321_uart_resource = {
+	.start		= IQ80321_UART,
+	.end		= IQ80321_UART + 7,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device iq80321_serial_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev		= {
+		.platform_data		= iq80321_serial_port,
+	},
+	.num_resources	= 1,
+	.resource	= &iq80321_uart_resource,
+};
+
+static void __init iq80321_init_machine(void)
+{
+	platform_device_register(&iop3xx_i2c0_device);
+	platform_device_register(&iop3xx_i2c1_device);
+	platform_device_register(&iq80321_flash_device);
+	platform_device_register(&iq80321_serial_device);
+}
+
+MACHINE_START(IQ80321, "Intel IQ80321")
+	/* Maintainer: Intel Corp. */
+	.phys_io	= IQ80321_UART,
+	.io_pg_offst	= ((IQ80321_UART) >> 18) & 0xfffc,
+	.boot_params	= 0xa0000100,
+	.map_io		= iq80321_map_io,
+	.init_irq	= iop32x_init_irq,
+	.timer		= &iq80321_timer,
+	.init_machine	= iq80321_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
new file mode 100644
index 0000000..69d6302
--- /dev/null
+++ b/arch/arm/mach-iop32x/irq.c
@@ -0,0 +1,76 @@
+/*
+ * arch/arm/mach-iop32x/irq.c
+ *
+ * Generic IOP32X IRQ handling functionality
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+static u32 iop32x_mask;
+
+static inline void intctl_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static inline void intstr_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static void
+iop32x_irq_mask(unsigned int irq)
+{
+	iop32x_mask &= ~(1 << irq);
+	intctl_write(iop32x_mask);
+}
+
+static void
+iop32x_irq_unmask(unsigned int irq)
+{
+	iop32x_mask |= 1 << irq;
+	intctl_write(iop32x_mask);
+}
+
+struct irq_chip ext_chip = {
+	.name	= "IOP32x",
+	.ack	= iop32x_irq_mask,
+	.mask	= iop32x_irq_mask,
+	.unmask	= iop32x_irq_unmask,
+};
+
+void __init iop32x_init_irq(void)
+{
+	int i;
+
+	intctl_write(0);
+	intstr_write(0);
+	if (machine_is_glantank() ||
+	    machine_is_iq80321() ||
+	    machine_is_iq31244() ||
+	    machine_is_n2100())
+		*IOP3XX_PCIIRSR = 0x0f;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_chip(i, &ext_chip);
+		set_irq_handler(i, do_level_IRQ);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
new file mode 100644
index 0000000..a2c94a4
--- /dev/null
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -0,0 +1,251 @@
+/*
+ * arch/arm/mach-iop32x/n2100.c
+ *
+ * Board support code for the Thecus N2100 platform.
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright 2003 (c) MontaVista, Software, Inc.
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * N2100 timer tick configuration.
+ */
+static void __init n2100_timer_init(void)
+{
+	/* 33.000 MHz crystal.  */
+	iop3xx_init_time(198000000);
+}
+
+static struct sys_timer n2100_timer = {
+	.init		= n2100_timer_init,
+	.offset		= iop3xx_gettimeoffset,
+};
+
+
+/*
+ * N2100 I/O.
+ */
+static struct map_desc n2100_io_desc[] __initdata = {
+	{	/* on-board devices */
+		.virtual	= N2100_UART,
+		.pfn		= __phys_to_pfn(N2100_UART),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init n2100_map_io(void)
+{
+	iop3xx_map_io();
+	iotable_init(n2100_io_desc, ARRAY_SIZE(n2100_io_desc));
+}
+
+
+/*
+ * N2100 PCI.
+ */
+static inline int __init
+n2100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (PCI_SLOT(dev->devfn) == 1) {
+		/* RTL8110SB #1 */
+		irq = IRQ_IOP32X_XINT0;
+	} else if (PCI_SLOT(dev->devfn) == 2) {
+		/* RTL8110SB #2 */
+		irq = IRQ_IOP32X_XINT1;
+	} else if (PCI_SLOT(dev->devfn) == 3) {
+		/* Sil3512 */
+		irq = IRQ_IOP32X_XINT2;
+	} else if (PCI_SLOT(dev->devfn) == 4 && pin == 1) {
+		/* VT6212 INTA */
+		irq = IRQ_IOP32X_XINT1;
+	} else if (PCI_SLOT(dev->devfn) == 4 && pin == 2) {
+		/* VT6212 INTB */
+		irq = IRQ_IOP32X_XINT0;
+	} else if (PCI_SLOT(dev->devfn) == 4 && pin == 3) {
+		/* VT6212 INTC */
+		irq = IRQ_IOP32X_XINT2;
+	} else if (PCI_SLOT(dev->devfn) == 5) {
+		/* Mini-PCI slot */
+		irq = IRQ_IOP32X_XINT3;
+	} else {
+		printk(KERN_ERR "n2100_pci_map_irq() called for unknown "
+			"device PCI:%d:%d:%d\n", dev->bus->number,
+			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		irq = -1;
+	}
+
+	return irq;
+}
+
+static struct hw_pci n2100_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iop3xx_pci_setup,
+	.preinit	= iop3xx_pci_preinit,
+	.scan		= iop3xx_pci_scan_bus,
+	.map_irq	= n2100_pci_map_irq,
+};
+
+static int __init n2100_pci_init(void)
+{
+	if (machine_is_n2100())
+		pci_common_init(&n2100_pci);
+
+	return 0;
+}
+
+subsys_initcall(n2100_pci_init);
+
+
+/*
+ * N2100 machine initialisation.
+ */
+static struct physmap_flash_data n2100_flash_data = {
+	.width		= 2,
+};
+
+static struct resource n2100_flash_resource = {
+	.start		= 0xf0000000,
+	.end		= 0xf0ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device n2100_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &n2100_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &n2100_flash_resource,
+};
+
+
+static struct plat_serial8250_port n2100_serial_port[] = {
+	{
+		.mapbase	= N2100_UART,
+		.membase	= (char *)N2100_UART,
+		.irq		= 0,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 0,
+		.uartclk	= 1843200,
+	},
+	{ },
+};
+
+static struct resource n2100_uart_resource = {
+	.start		= N2100_UART,
+	.end		= N2100_UART + 7,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device n2100_serial_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev		= {
+		.platform_data		= n2100_serial_port,
+	},
+	.num_resources	= 1,
+	.resource	= &n2100_uart_resource,
+};
+
+
+/*
+ * Pull PCA9532 GPIO #8 low to power off the machine.
+ */
+static void n2100_power_off(void)
+{
+	local_irq_disable();
+
+	/* Start condition, I2C address of PCA9532, write transaction.  */
+	*IOP3XX_IDBR0 = 0xc0;
+	*IOP3XX_ICR0 = 0xe9;
+	mdelay(1);
+
+	/* Write address 0x08.  */
+	*IOP3XX_IDBR0 = 0x08;
+	*IOP3XX_ICR0 = 0xe8;
+	mdelay(1);
+
+	/* Write data 0x01, stop condition.  */
+	*IOP3XX_IDBR0 = 0x01;
+	*IOP3XX_ICR0 = 0xea;
+
+	while (1)
+		;
+}
+
+
+static struct timer_list power_button_poll_timer;
+
+static void power_button_poll(unsigned long dummy)
+{
+	if (gpio_line_get(N2100_POWER_BUTTON) == 0) {
+		ctrl_alt_del();
+		return;
+	}
+
+	power_button_poll_timer.expires = jiffies + (HZ / 10);
+	add_timer(&power_button_poll_timer);
+}
+
+
+static void __init n2100_init_machine(void)
+{
+	platform_device_register(&iop3xx_i2c0_device);
+	platform_device_register(&n2100_flash_device);
+	platform_device_register(&n2100_serial_device);
+
+	pm_power_off = n2100_power_off;
+
+	init_timer(&power_button_poll_timer);
+	power_button_poll_timer.function = power_button_poll;
+	power_button_poll_timer.expires = jiffies + (HZ / 10);
+	add_timer(&power_button_poll_timer);
+}
+
+MACHINE_START(N2100, "Thecus N2100")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= N2100_UART,
+	.io_pg_offst	= ((N2100_UART) >> 18) & 0xfffc,
+	.boot_params	= 0xa0000100,
+	.map_io		= n2100_map_io,
+	.init_irq	= iop32x_init_irq,
+	.timer		= &n2100_timer,
+	.init_machine	= n2100_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop33x/Kconfig b/arch/arm/mach-iop33x/Kconfig
new file mode 100644
index 0000000..9aa016b
--- /dev/null
+++ b/arch/arm/mach-iop33x/Kconfig
@@ -0,0 +1,21 @@
+if ARCH_IOP33X
+
+menu "IOP33x Implementation Options"
+
+comment "IOP33x Platform Types"
+
+config ARCH_IQ80331
+	bool "Enable support for IQ80331"
+	help
+	  Say Y here if you want to run your kernel on the Intel IQ80331
+	  evaluation kit for the IOP331 chipset.
+
+config MACH_IQ80332
+	bool "Enable support for IQ80332"
+	help
+	  Say Y here if you want to run your kernel on the Intel IQ80332
+	  evaluation kit for the IOP332 chipset.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-iop33x/Makefile b/arch/arm/mach-iop33x/Makefile
new file mode 100644
index 0000000..90081d8
--- /dev/null
+++ b/arch/arm/mach-iop33x/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y			:= irq.o uart.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+obj-$(CONFIG_ARCH_IQ80331) += iq80331.o
+obj-$(CONFIG_MACH_IQ80332) += iq80332.o
diff --git a/arch/arm/mach-iop33x/Makefile.boot b/arch/arm/mach-iop33x/Makefile.boot
new file mode 100644
index 0000000..67039c3
--- /dev/null
+++ b/arch/arm/mach-iop33x/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
new file mode 100644
index 0000000..97a7b74
--- /dev/null
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/mach-iop33x/iq80331.c
+ *
+ * Board support code for the Intel IQ80331 platform.
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * IQ80331 timer tick configuration.
+ */
+static void __init iq80331_timer_init(void)
+{
+	/* D-Step parts run at a higher internal bus frequency */
+	if (*IOP3XX_ATURID >= 0xa)
+		iop3xx_init_time(333000000);
+	else
+		iop3xx_init_time(266000000);
+}
+
+static struct sys_timer iq80331_timer = {
+	.init		= iq80331_timer_init,
+	.offset		= iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ80331 PCI.
+ */
+static inline int __init
+iq80331_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (slot == 1 && pin == 1) {
+		/* PCI-X Slot INTA */
+		irq = IRQ_IOP33X_XINT1;
+	} else if (slot == 1 && pin == 2) {
+		/* PCI-X Slot INTB */
+		irq = IRQ_IOP33X_XINT2;
+	} else if (slot == 1 && pin == 3) {
+		/* PCI-X Slot INTC */
+		irq = IRQ_IOP33X_XINT3;
+	} else if (slot == 1 && pin == 4) {
+		/* PCI-X Slot INTD */
+		irq = IRQ_IOP33X_XINT0;
+	} else if (slot == 2) {
+		/* GigE */
+		irq = IRQ_IOP33X_XINT2;
+	} else {
+		printk(KERN_ERR "iq80331_pci_map_irq() called for unknown "
+			"device PCI:%d:%d:%d\n", dev->bus->number,
+			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		irq = -1;
+	}
+
+	return irq;
+}
+
+static struct hw_pci iq80331_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iop3xx_pci_setup,
+	.preinit	= iop3xx_pci_preinit,
+	.scan		= iop3xx_pci_scan_bus,
+	.map_irq	= iq80331_pci_map_irq,
+};
+
+static int __init iq80331_pci_init(void)
+{
+	if (machine_is_iq80331())
+		pci_common_init(&iq80331_pci);
+
+	return 0;
+}
+
+subsys_initcall(iq80331_pci_init);
+
+
+/*
+ * IQ80331 machine initialisation.
+ */
+static struct physmap_flash_data iq80331_flash_data = {
+	.width		= 1,
+};
+
+static struct resource iq80331_flash_resource = {
+	.start		= 0xc0000000,
+	.end		= 0xc07fffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device iq80331_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &iq80331_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &iq80331_flash_resource,
+};
+
+static void __init iq80331_init_machine(void)
+{
+	platform_device_register(&iop3xx_i2c0_device);
+	platform_device_register(&iop3xx_i2c1_device);
+	platform_device_register(&iop33x_uart0_device);
+	platform_device_register(&iop33x_uart1_device);
+	platform_device_register(&iq80331_flash_device);
+}
+
+MACHINE_START(IQ80331, "Intel IQ80331")
+	/* Maintainer: Intel Corp. */
+	.phys_io	= 0xfefff000,
+	.io_pg_offst	= ((0xfffff000) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.map_io		= iop3xx_map_io,
+	.init_irq	= iop33x_init_irq,
+	.timer		= &iq80331_timer,
+	.init_machine	= iq80331_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
new file mode 100644
index 0000000..9887bfc
--- /dev/null
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/mach-iop33x/iq80332.c
+ *
+ * Board support code for the Intel IQ80332 platform.
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * IQ80332 timer tick configuration.
+ */
+static void __init iq80332_timer_init(void)
+{
+	/* D-Step parts and the iop333 run at a higher internal bus frequency */
+	if (*IOP3XX_ATURID >= 0xa || *IOP3XX_ATUDID == 0x374)
+		iop3xx_init_time(333000000);
+	else
+		iop3xx_init_time(266000000);
+}
+
+static struct sys_timer iq80332_timer = {
+	.init		= iq80332_timer_init,
+	.offset		= iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ80332 PCI.
+ */
+static inline int __init
+iq80332_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (slot == 4 && pin == 1) {
+		/* PCI-X Slot INTA */
+		irq = IRQ_IOP33X_XINT0;
+	} else if (slot == 4 && pin == 2) {
+		/* PCI-X Slot INTB */
+		irq = IRQ_IOP33X_XINT1;
+	} else if (slot == 4 && pin == 3) {
+		/* PCI-X Slot INTC */
+		irq = IRQ_IOP33X_XINT2;
+	} else if (slot == 4 && pin == 4) {
+		/* PCI-X Slot INTD */
+		irq = IRQ_IOP33X_XINT3;
+	} else if (slot == 6) {
+		/* GigE */
+		irq = IRQ_IOP33X_XINT2;
+	} else {
+		printk(KERN_ERR "iq80332_pci_map_irq() called for unknown "
+			"device PCI:%d:%d:%d\n", dev->bus->number,
+			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		irq = -1;
+	}
+
+	return irq;
+}
+
+static struct hw_pci iq80332_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iop3xx_pci_setup,
+	.preinit	= iop3xx_pci_preinit,
+	.scan		= iop3xx_pci_scan_bus,
+	.map_irq	= iq80332_pci_map_irq,
+};
+
+static int __init iq80332_pci_init(void)
+{
+	if (machine_is_iq80332())
+		pci_common_init(&iq80332_pci);
+
+	return 0;
+}
+
+subsys_initcall(iq80332_pci_init);
+
+
+/*
+ * IQ80332 machine initialisation.
+ */
+static struct physmap_flash_data iq80332_flash_data = {
+	.width		= 1,
+};
+
+static struct resource iq80332_flash_resource = {
+	.start		= 0xc0000000,
+	.end		= 0xc07fffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device iq80332_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &iq80332_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &iq80332_flash_resource,
+};
+
+static void __init iq80332_init_machine(void)
+{
+	platform_device_register(&iop3xx_i2c0_device);
+	platform_device_register(&iop3xx_i2c1_device);
+	platform_device_register(&iop33x_uart0_device);
+	platform_device_register(&iop33x_uart1_device);
+	platform_device_register(&iq80332_flash_device);
+}
+
+MACHINE_START(IQ80332, "Intel IQ80332")
+	/* Maintainer: Intel Corp. */
+	.phys_io	= 0xfefff000,
+	.io_pg_offst	= ((0xfffff000) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.map_io		= iop3xx_map_io,
+	.init_irq	= iop33x_init_irq,
+	.timer		= &iq80332_timer,
+	.init_machine	= iq80332_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c
new file mode 100644
index 0000000..63304b3
--- /dev/null
+++ b/arch/arm/mach-iop33x/irq.c
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-iop33x/irq.c
+ *
+ * Generic IOP331 IRQ handling functionality
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+static u32 iop33x_mask0;
+static u32 iop33x_mask1;
+
+static inline void intctl0_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static inline void intctl1_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c1, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static inline void intstr0_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c2, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static inline void intstr1_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c3, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static inline void intbase_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c12, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static inline void intsize_write(u32 val)
+{
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c13, c0, 0" : : "r" (val));
+	iop3xx_cp6_disable();
+}
+
+static void
+iop33x_irq_mask1 (unsigned int irq)
+{
+	iop33x_mask0 &= ~(1 << irq);
+	intctl0_write(iop33x_mask0);
+}
+
+static void
+iop33x_irq_mask2 (unsigned int irq)
+{
+	iop33x_mask1 &= ~(1 << (irq - 32));
+	intctl1_write(iop33x_mask1);
+}
+
+static void
+iop33x_irq_unmask1(unsigned int irq)
+{
+	iop33x_mask0 |= 1 << irq;
+	intctl0_write(iop33x_mask0);
+}
+
+static void
+iop33x_irq_unmask2(unsigned int irq)
+{
+	iop33x_mask1 |= (1 << (irq - 32));
+	intctl1_write(iop33x_mask1);
+}
+
+struct irq_chip iop33x_irqchip1 = {
+	.name	= "IOP33x-1",
+	.ack	= iop33x_irq_mask1,
+	.mask	= iop33x_irq_mask1,
+	.unmask	= iop33x_irq_unmask1,
+};
+
+struct irq_chip iop33x_irqchip2 = {
+	.name	= "IOP33x-2",
+	.ack	= iop33x_irq_mask2,
+	.mask	= iop33x_irq_mask2,
+	.unmask	= iop33x_irq_unmask2,
+};
+
+void __init iop33x_init_irq(void)
+{
+	int i;
+
+	intctl0_write(0);
+	intctl1_write(0);
+	intstr0_write(0);
+	intstr1_write(0);
+	intbase_write(0);
+	intsize_write(1);
+	if (machine_is_iq80331())
+		*IOP3XX_PCIIRSR = 0x0f;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_chip(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2);
+		set_irq_handler(i, do_level_IRQ);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
diff --git a/arch/arm/mach-iop33x/uart.c b/arch/arm/mach-iop33x/uart.c
new file mode 100644
index 0000000..ac297cd
--- /dev/null
+++ b/arch/arm/mach-iop33x/uart.c
@@ -0,0 +1,105 @@
+/*
+ * arch/arm/mach-iop33x/uart.c
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2004 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop3xx.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#define IOP33X_UART_XTAL 33334000
+
+static struct plat_serial8250_port iop33x_uart0_data[] = {
+	{
+		.membase	= (char *)IOP33X_UART0_VIRT,
+		.mapbase	= IOP33X_UART0_PHYS,
+		.irq		= IRQ_IOP33X_UART0,
+		.uartclk	= IOP33X_UART_XTAL,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_SKIP_TEST,
+	},
+	{ },
+};
+
+static struct resource iop33x_uart0_resources[] = {
+	[0] = {
+		.start	= IOP33X_UART0_PHYS,
+		.end	= IOP33X_UART0_PHYS + 0x3f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_IOP33X_UART0,
+		.end	= IRQ_IOP33X_UART0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device iop33x_uart0_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev		= {
+		.platform_data		= iop33x_uart0_data,
+	},
+	.num_resources	= 2,
+	.resource	= iop33x_uart0_resources,
+};
+
+
+static struct resource iop33x_uart1_resources[] = {
+	[0] = {
+		.start	= IOP33X_UART1_PHYS,
+		.end	= IOP33X_UART1_PHYS + 0x3f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_IOP33X_UART1,
+		.end	= IRQ_IOP33X_UART1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct plat_serial8250_port iop33x_uart1_data[] = {
+	{
+		.membase	= (char *)IOP33X_UART1_VIRT,
+		.mapbase	= IOP33X_UART1_PHYS,
+		.irq		= IRQ_IOP33X_UART1,
+		.uartclk	= IOP33X_UART_XTAL,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_SKIP_TEST,
+	},
+	{ },
+};
+
+struct platform_device iop33x_uart1_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM1,
+	.dev		= {
+		.platform_data		= iop33x_uart1_data,
+	},
+	.num_resources	= 2,
+	.resource	= iop33x_uart1_resources,
+};
diff --git a/arch/arm/mach-iop3xx/Kconfig b/arch/arm/mach-iop3xx/Kconfig
deleted file mode 100644
index 4422f23..0000000
--- a/arch/arm/mach-iop3xx/Kconfig
+++ /dev/null
@@ -1,66 +0,0 @@
-if ARCH_IOP3XX
-
-menu "IOP3xx Implementation Options"
-
-comment "IOP3xx Platform Types"
-
-config ARCH_IQ80321
-	bool "Enable support for IQ80321"
-	select ARCH_IOP321
-	help
-	  Say Y here if you want to run your kernel on the Intel IQ80321
-	  evaluation kit for the IOP321 chipset.
-
-config ARCH_IQ31244
-	bool "Enable support for IQ31244"
-	select ARCH_IOP321
-	help
-	  Say Y here if you want to run your kernel on the Intel IQ31244
-	  evaluation kit for the IOP321 chipset.
-
-config ARCH_IQ80331
-	bool "Enable support for IQ80331"
-	select ARCH_IOP331
-	help
-	  Say Y here if you want to run your kernel on the Intel IQ80331
-	  evaluation kit for the IOP331 chipset.
-
-config MACH_IQ80332
-	bool "Enable support for IQ80332"
-	select ARCH_IOP331
-	help
-	  Say Y here if you want to run your kernel on the Intel IQ80332
-	  evaluation kit for the IOP332 chipset.
-
-config ARCH_EP80219
-	bool "Enable support for EP80219"
-	select ARCH_IOP321
-	select ARCH_IQ31244
-	help
-	  Say Y here if you want to run your kernel on the Intel EP80219
-	  evaluation kit for the Intel 80219 chipset (a IOP321 variant).
-
-# Which IOP variant are we running?
-config ARCH_IOP321
-	bool
-	help
-	  The IQ80321 uses the IOP321 variant.
-	  The IQ31244 and EP80219 uses the IOP321 variant.
-
-config ARCH_IOP331
-	bool
-	default ARCH_IQ80331
-	help
-	  The IQ80331, IQ80332, and IQ80333 uses the IOP331 variant.
-
-comment "IOP3xx Chipset Features"
-
-config IOP331_STEPD
-	bool "Chip stepping D of the IOP80331 processor or IOP80333"
-	depends on (ARCH_IOP331)
-	help
-	  Say Y here if you have StepD of the IOP80331 or IOP8033
-	  based platforms.
-
-endmenu
-endif
diff --git a/arch/arm/mach-iop3xx/Makefile b/arch/arm/mach-iop3xx/Makefile
deleted file mode 100644
index b17eb1f..0000000
--- a/arch/arm/mach-iop3xx/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y			:= common.o
-
-obj-m			:=
-obj-n			:=
-obj-			:=
-
-obj-$(CONFIG_ARCH_IOP321)  += iop321-setup.o iop321-irq.o iop321-pci.o iop321-time.o
-
-obj-$(CONFIG_ARCH_IOP331)  += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o
-
-obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o
-
-obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o
-
-obj-$(CONFIG_ARCH_IQ80331) += iq80331-mm.o iq80331-pci.o
-
-obj-$(CONFIG_MACH_IQ80332) += iq80332-mm.o iq80332-pci.o
diff --git a/arch/arm/mach-iop3xx/Makefile.boot b/arch/arm/mach-iop3xx/Makefile.boot
deleted file mode 100644
index 6387aa2..0000000
--- a/arch/arm/mach-iop3xx/Makefile.boot
+++ /dev/null
@@ -1,9 +0,0 @@
-   zreladdr-y	:= 0xa0008000
-params_phys-y	:= 0xa0000100
-initrd_phys-y	:= 0xa0800000
-ifeq ($(CONFIG_ARCH_IOP331),y)
-   zreladdr-y	:= 0x00008000
-params_phys-y	:= 0x00000100
-initrd_phys-y	:= 0x00800000
-endif
-
diff --git a/arch/arm/mach-iop3xx/common.c b/arch/arm/mach-iop3xx/common.c
deleted file mode 100644
index d7f50e5..0000000
--- a/arch/arm/mach-iop3xx/common.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/common.c
- *
- * Common routines shared across all IOP3xx implementations
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright 2003 (c) MontaVista, Software, Inc.
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/delay.h>
-#include <asm/hardware.h>
-
-/*
- * Shared variables
- */
-unsigned long iop3xx_pcibios_min_io = 0;
-unsigned long iop3xx_pcibios_min_mem = 0;
-
-#ifdef CONFIG_ARCH_EP80219
-#include <linux/kernel.h>
-/*
- * Default power-off for EP80219
- */
-
-static inline void ep80219_send_to_pic(__u8 c) {
-}
-
-void ep80219_power_off(void)
-{
-	/*
-     * This function will send a SHUTDOWN_COMPLETE message to the PIC controller
-     * over I2C.  We are not using the i2c subsystem since we are going to power
-     * off and it may be removed
-     */
-
-	/* Send the Address byte w/ the start condition */
-	*IOP321_IDBR1 = 0x60;
-	*IOP321_ICR1 = 0xE9;
-    mdelay(1);
-
-	/* Send the START_MSG byte w/ no start or stop condition */
-	*IOP321_IDBR1 = 0x0F;
-	*IOP321_ICR1 = 0xE8;
-    mdelay(1);
-
-	/* Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or stop condition */
-	*IOP321_IDBR1 = 0x03;
-	*IOP321_ICR1 = 0xE8;
-    mdelay(1);
-
-	/* Send an ignored byte w/ stop condition */
-	*IOP321_IDBR1 = 0x00;
-	*IOP321_ICR1 = 0xEA;
-
-	while (1) ;
-}
-
-#include <linux/init.h>
-#include <linux/pm.h>
-
-static int __init ep80219_init(void)
-{
-	pm_power_off = ep80219_power_off;
-	return 0;
-}
-arch_initcall(ep80219_init);
-#endif
diff --git a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c
deleted file mode 100644
index 88ac333..0000000
--- a/arch/arm/mach-iop3xx/iop321-irq.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop321-irq.c
- *
- * Generic IOP321 IRQ handling functionality
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * 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.
- *
- * Added IOP3XX chipset and IQ80321 board masking code.
- *
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-#include <asm/mach-types.h>
-
-static u32 iop321_mask /* = 0 */;
-
-static inline void intctl_write(u32 val)
-{
-	asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
-}
-
-static inline void intstr_write(u32 val)
-{
-	asm volatile("mcr p6,0,%0,c4,c0,0"::"r" (val));
-}
-
-static void
-iop321_irq_mask (unsigned int irq)
-{
-
-	iop321_mask &= ~(1 << (irq - IOP321_IRQ_OFS));
-
-	intctl_write(iop321_mask);
-}
-
-static void
-iop321_irq_unmask (unsigned int irq)
-{
-	iop321_mask |= (1 << (irq - IOP321_IRQ_OFS));
-
-	intctl_write(iop321_mask);
-}
-
-struct irq_chip ext_chip = {
-	.name	= "IOP",
-	.ack    = iop321_irq_mask,
-	.mask   = iop321_irq_mask,
-	.unmask = iop321_irq_unmask,
-};
-
-void __init iop321_init_irq(void)
-{
-	unsigned int i, tmp;
-
-	/* Enable access to coprocessor 6 for dealing with IRQs.
-	 * From RMK:
-	 * Basically, the Intel documentation here is poor.  It appears that
-	 * you need to set the bit to be able to access the coprocessor from
-	 * SVC mode.  Whether that allows access from user space or not is
-	 * unclear.
-	 */
-	asm volatile (
-		"mrc p15, 0, %0, c15, c1, 0\n\t"
-		"orr %0, %0, %1\n\t"
-		"mcr p15, 0, %0, c15, c1, 0\n\t"
-		/* The action is delayed, so we have to do this: */
-		"mrc p15, 0, %0, c15, c1, 0\n\t"
-		"mov %0, %0\n\t"
-		"sub pc, pc, #4"
-		: "=r" (tmp) : "i" (1 << 6) );
-
-	intctl_write(0);		// disable all interrupts
-	intstr_write(0);		// treat all as IRQ
-	if(machine_is_iq80321() ||
-	   machine_is_iq31244()) 	// all interrupts are inputs to chip
-		*IOP321_PCIIRSR = 0x0f;
-
-	for(i = IOP321_IRQ_OFS; i < NR_IOP321_IRQS; i++)
-	{
-		set_irq_chip(i, &ext_chip);
-		set_irq_handler(i, do_level_IRQ);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-
-	}
-}
-
diff --git a/arch/arm/mach-iop3xx/iop321-pci.c b/arch/arm/mach-iop3xx/iop321-pci.c
deleted file mode 100644
index 8ba6a0e..0000000
--- a/arch/arm/mach-iop3xx/iop321-pci.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop321-pci.c
- *
- * PCI support for the Intel IOP321 chipset
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/hardware.h>
-#include <asm/mach/pci.h>
-
-#include <asm/arch/iop321.h>
-
-// #define DEBUG
-
-#ifdef DEBUG
-#define  DBG(x...) printk(x)
-#else
-#define  DBG(x...) do { } while (0)
-#endif
-
-/*
- * This routine builds either a type0 or type1 configuration command.  If the
- * bus is on the 80321 then a type0 made, else a type1 is created.
- */
-static u32 iop321_cfg_address(struct pci_bus *bus, int devfn, int where)
-{
-	struct pci_sys_data *sys = bus->sysdata;
-	u32 addr;
-
-	if (sys->busnr == bus->number)
-		addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
-	else
-		addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
-
-	addr |=	PCI_FUNC(devfn) << 8 | (where & ~3);
-
-	return addr;
-}
-
-/*
- * This routine checks the status of the last configuration cycle.  If an error
- * was detected it returns a 1, else it returns a 0.  The errors being checked
- * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
- * the discovery stage.
- */
-static int iop321_pci_status(void)
-{
-	unsigned int status;
-	int ret = 0;
-
-	/*
-	 * Check the status registers.
-	 */
-	status = *IOP321_ATUSR;
-	if (status & 0xf900)
-	{
-		DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
-		*IOP321_ATUSR = status & 0xf900;
-		ret = 1;
-	}
-	status = *IOP321_ATUISR;
-	if (status & 0x679f)
-	{
-		DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
-		*IOP321_ATUISR = status & 0x679f;
-		ret = 1;
-	}
-	return ret;
-}
-
-/*
- * Simply write the address register and read the configuration
- * data.  Note that the 4 nop's ensure that we are able to handle
- * a delayed abort (in theory.)
- */
-static inline u32 iop321_read(unsigned long addr)
-{
-	u32 val;
-
-	__asm__ __volatile__(
-		"str	%1, [%2]\n\t"
-		"ldr	%0, [%3]\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		: "=r" (val)
-		: "r" (addr), "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
-
-	return val;
-}
-
-/*
- * The read routines must check the error status of the last configuration
- * cycle.  If there was an error, the routine returns all hex f's.
- */
-static int
-iop321_read_config(struct pci_bus *bus, unsigned int devfn, int where,
-		int size, u32 *value)
-{
-	unsigned long addr = iop321_cfg_address(bus, devfn, where);
-	u32 val = iop321_read(addr) >> ((where & 3) * 8);
-
-	if( iop321_pci_status() )
-		val = 0xffffffff;
-
-	*value = val;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where,
-		int size, u32 value)
-{
-	unsigned long addr = iop321_cfg_address(bus, devfn, where);
-	u32 val;
-
-	if (size != 4) {
-		val = iop321_read(addr);
-		if (!iop321_pci_status() == 0)
-			return PCIBIOS_SUCCESSFUL;
-
-		where = (where & 3) * 8;
-
-		if (size == 1)
-			val &= ~(0xff << where);
-		else
-			val &= ~(0xffff << where);
-
-		*IOP321_OCCDR = val | value << where;
-	} else {
-		asm volatile(
-			"str	%1, [%2]\n\t"
-			"str	%0, [%3]\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			:
-			: "r" (value), "r" (addr),
-			  "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop321_ops = {
-	.read	= iop321_read_config,
-	.write	= iop321_write_config,
-};
-
-/*
- * When a PCI device does not exist during config cycles, the 80200 gets a
- * bus error instead of returning 0xffffffff. This handler simply returns.
- */
-int
-iop321_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
-	DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
-		addr, fsr, regs->ARM_pc, regs->ARM_lr);
-
-	/*
-	 * If it was an imprecise abort, then we need to correct the
-	 * return address to be _after_ the instruction.
-	 */
-	if (fsr & (1 << 10))
-		regs->ARM_pc += 4;
-
-	return 0;
-}
-
-/*
- * Scan an IOP321 PCI bus.  sys->bus defines which bus we scan.
- */
-struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	return pci_scan_bus(sys->busnr, &iop321_ops, sys);
-}
-
-void iop321_init(void)
-{
-	DBG("PCI:  Intel 80321 PCI init code.\n");
-	DBG("ATU: IOP321_ATUCMD=0x%04x\n", *IOP321_ATUCMD);
-	DBG("ATU: IOP321_OMWTVR0=0x%04x, IOP321_OIOWTVR=0x%04x\n",
-			*IOP321_OMWTVR0,
-			*IOP321_OIOWTVR);
-	DBG("ATU: IOP321_ATUCR=0x%08x\n", *IOP321_ATUCR);
-	DBG("ATU: IOP321_IABAR0=0x%08x IOP321_IALR0=0x%08x IOP321_IATVR0=%08x\n",
-			*IOP321_IABAR0, *IOP321_IALR0, *IOP321_IATVR0);
-	DBG("ATU: IOP321_OMWTVR0=0x%08x\n", *IOP321_OMWTVR0);
-	DBG("ATU: IOP321_IABAR1=0x%08x IOP321_IALR1=0x%08x\n",
-			*IOP321_IABAR1, *IOP321_IALR1);
-	DBG("ATU: IOP321_ERBAR=0x%08x IOP321_ERLR=0x%08x IOP321_ERTVR=%08x\n",
-			*IOP321_ERBAR, *IOP321_ERLR, *IOP321_ERTVR);
-	DBG("ATU: IOP321_IABAR2=0x%08x IOP321_IALR2=0x%08x IOP321_IATVR2=%08x\n",
-			*IOP321_IABAR2, *IOP321_IALR2, *IOP321_IATVR2);
-	DBG("ATU: IOP321_IABAR3=0x%08x IOP321_IALR3=0x%08x IOP321_IATVR3=%08x\n",
-			*IOP321_IABAR3, *IOP321_IALR3, *IOP321_IATVR3);
-
-	hook_fault_code(16+6, iop321_pci_abort, SIGBUS, "imprecise external abort");
-}
-
diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
deleted file mode 100644
index b6d0969..0000000
--- a/arch/arm/mach-iop3xx/iop321-setup.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop321-setup.c
- *
- * Author: Nicolas Pitre <nico@cam.org>
- * Copyright (C) 2001 MontaVista Software, Inc.
- * Copyright (C) 2004 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#define IOP321_UART_XTAL 1843200
-
-/*
- * Standard IO mapping for all IOP321 based systems
- */
-static struct map_desc iop321_std_desc[] __initdata = {
-	 {	/* mem mapped registers */
-		.virtual	= IOP321_VIRT_MEM_BASE,
-		.pfn		= __phys_to_pfn(IOP321_PHYS_MEM_BASE),
-		.length		= 0x00002000,
-		.type		= MT_DEVICE
-	 }, {	/* PCI IO space */
-		.virtual	= IOP321_PCI_LOWER_IO_VA,
-		.pfn		= __phys_to_pfn(IOP321_PCI_LOWER_IO_PA),
-		.length		= IOP321_PCI_IO_WINDOW_SIZE,
-		.type		= MT_DEVICE
-	 }
-};
-
-#ifdef CONFIG_ARCH_IQ80321
-#define UARTBASE IQ80321_UART
-#define IRQ_UART IRQ_IQ80321_UART
-#endif
-
-#ifdef CONFIG_ARCH_IQ31244
-#define UARTBASE IQ31244_UART
-#define IRQ_UART IRQ_IQ31244_UART
-#endif
-
-static struct uart_port iop321_serial_ports[] = {
-	{
-		.membase	= (char*)(UARTBASE),
-		.mapbase	= (UARTBASE),
-		.irq		= IRQ_UART,
-		.flags		= UPF_SKIP_TEST,
-		.iotype		= UPIO_MEM,
-		.regshift	= 0,
-		.uartclk	= IOP321_UART_XTAL,
-		.line		= 0,
-		.type		= PORT_16550A,
-		.fifosize	= 16
-	}
-};
-
-static struct resource iop32x_i2c_0_resources[] = {
-	[0] = {
-		.start = 0xfffff680,
-		.end = 0xfffff698,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IOP321_I2C_0,
-		.end = IRQ_IOP321_I2C_0,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-static struct resource iop32x_i2c_1_resources[] = {
-	[0] = {
-		.start = 0xfffff6a0,
-		.end = 0xfffff6b8,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IOP321_I2C_1,
-		.end = IRQ_IOP321_I2C_1,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-static struct platform_device iop32x_i2c_0_controller = {
-	.name = "IOP3xx-I2C",
-	.id = 0,
-	.num_resources = 2,
-	.resource = iop32x_i2c_0_resources
-};
-
-static struct platform_device iop32x_i2c_1_controller = {
-	.name = "IOP3xx-I2C",
-	.id = 1,
-	.num_resources = 2,
-	.resource = iop32x_i2c_1_resources
-};
-
-static struct platform_device *iop32x_devices[] __initdata = {
-	&iop32x_i2c_0_controller,
-	&iop32x_i2c_1_controller
-};
-
-void __init iop32x_init(void)
-{
-	if(iop_is_321())
-	{
-		platform_add_devices(iop32x_devices,
-				ARRAY_SIZE(iop32x_devices));
-	}
-}
-
-void __init iop321_map_io(void)
-{
-	iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
-	early_serial_setup(&iop321_serial_ports[0]);
-}
-
-#ifdef CONFIG_ARCH_IQ80321
-extern void iq80321_map_io(void);
-extern struct sys_timer iop321_timer;
-extern void iop321_init_time(void);
-#endif
-
-#ifdef CONFIG_ARCH_IQ31244
-extern void iq31244_map_io(void);
-extern struct sys_timer iop321_timer;
-extern void iop321_init_time(void);
-#endif
-
-#if defined(CONFIG_ARCH_IQ80321)
-MACHINE_START(IQ80321, "Intel IQ80321")
-	/* Maintainer: Intel Corporation */
-	.phys_io	= IQ80321_UART,
-	.io_pg_offst	= ((IQ80321_UART) >> 18) & 0xfffc,
-	.map_io		= iq80321_map_io,
-	.init_irq	= iop321_init_irq,
-	.timer		= &iop321_timer,
-	.boot_params	= 0xa0000100,
-	.init_machine	= iop32x_init,
-MACHINE_END
-#elif defined(CONFIG_ARCH_IQ31244)
-MACHINE_START(IQ31244, "Intel IQ31244")
-	/* Maintainer: Intel Corp. */
-	.phys_io	= IQ31244_UART,
-	.io_pg_offst	= ((IQ31244_UART) >> 18) & 0xfffc,
-	.map_io		= iq31244_map_io,
-	.init_irq	= iop321_init_irq,
-	.timer		= &iop321_timer,
-	.boot_params	= 0xa0000100,
-	.init_machine	= iop32x_init,
-MACHINE_END
-#else
-#error No machine descriptor defined for this IOP3XX implementation
-#endif
diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
deleted file mode 100644
index 04b1a6f7..0000000
--- a/arch/arm/mach-iop3xx/iop321-time.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop321-time.c
- *
- * Timer code for IOP321 based systems
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright 2002-2003 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-#define IOP321_TIME_SYNC 0
-
-static inline unsigned long get_elapsed(void)
-{
-	return LATCH - *IOP321_TU_TCR0;
-}
-
-static unsigned long iop321_gettimeoffset(void)
-{
-	unsigned long elapsed, usec;
-	u32 tisr1, tisr2;
-
-	/*
-	 * If an interrupt was pending before we read the timer,
-	 * we've already wrapped.  Factor this into the time.
-	 * If an interrupt was pending after we read the timer,
-	 * it may have wrapped between checking the interrupt
-	 * status and reading the timer.  Re-read the timer to
-	 * be sure its value is after the wrap.
-	 */
-
-	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
-	elapsed = get_elapsed();
-	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
-
-	if(tisr1 & 1)
-		elapsed += LATCH;
-	else if (tisr2 & 1)
-		elapsed = LATCH + get_elapsed();
-
-	/*
-	 * Now convert them to usec.
-	 */
-	usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
-
-	return usec;
-}
-
-static irqreturn_t
-iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	u32 tisr;
-
-	write_seqlock(&xtime_lock);
-
-	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
-	tisr |= 1;
-	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
-
-	timer_tick(regs);
-
-	write_sequnlock(&xtime_lock);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction iop321_timer_irq = {
-	.name		= "IOP321 Timer Tick",
-	.handler	= iop321_timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-};
-
-static void __init iop321_timer_init(void)
-{
-	u32 timer_ctl;
-
-	setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
-
-	timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
-			IOP321_TMR_RATIO_1_1;
-
-	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
-
-	asm volatile("mcr p6, 0, %0, c0, c1, 0"	: : "r" (timer_ctl));
-}
-
-struct sys_timer iop321_timer = {
-	.init		= &iop321_timer_init,
-	.offset		= iop321_gettimeoffset,
-};
diff --git a/arch/arm/mach-iop3xx/iop331-irq.c b/arch/arm/mach-iop3xx/iop331-irq.c
deleted file mode 100644
index cab1172..0000000
--- a/arch/arm/mach-iop3xx/iop331-irq.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop331-irq.c
- *
- * Generic IOP331 IRQ handling functionality
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-#include <asm/mach-types.h>
-
-static u32 iop331_mask0 = 0;
-static u32 iop331_mask1 = 0;
-
-static inline void intctl_write0(u32 val)
-{
-    // INTCTL0
-	asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
-}
-
-static inline void intctl_write1(u32 val)
-{
-    // INTCTL1
-    asm volatile("mcr p6,0,%0,c1,c0,0"::"r" (val));
-}
-
-static inline void intstr_write0(u32 val)
-{
-    // INTSTR0
-	asm volatile("mcr p6,0,%0,c2,c0,0"::"r" (val));
-}
-
-static inline void intstr_write1(u32 val)
-{
-    // INTSTR1
-	asm volatile("mcr p6,0,%0,c3,c0,0"::"r" (val));
-}
-
-static void
-iop331_irq_mask1 (unsigned int irq)
-{
-        iop331_mask0 &= ~(1 << (irq - IOP331_IRQ_OFS));
-        intctl_write0(iop331_mask0);
-}
-
-static void
-iop331_irq_mask2 (unsigned int irq)
-{
-        iop331_mask1 &= ~(1 << (irq - IOP331_IRQ_OFS - 32));
-        intctl_write1(iop331_mask1);
-}
-
-static void
-iop331_irq_unmask1(unsigned int irq)
-{
-        iop331_mask0 |= (1 << (irq - IOP331_IRQ_OFS));
-        intctl_write0(iop331_mask0);
-}
-
-static void
-iop331_irq_unmask2(unsigned int irq)
-{
-        iop331_mask1 |= (1 << (irq - IOP331_IRQ_OFS - 32));
-        intctl_write1(iop331_mask1);
-}
-
-struct irq_chip iop331_irqchip1 = {
-	.name	= "IOP-1",
-	.ack    = iop331_irq_mask1,
-	.mask   = iop331_irq_mask1,
-	.unmask = iop331_irq_unmask1,
-};
-
-struct irq_chip iop331_irqchip2 = {
-	.name	= "IOP-2",
-	.ack    = iop331_irq_mask2,
-	.mask   = iop331_irq_mask2,
-	.unmask = iop331_irq_unmask2,
-};
-
-void __init iop331_init_irq(void)
-{
-	unsigned int i, tmp;
-
-	/* Enable access to coprocessor 6 for dealing with IRQs.
-	 * From RMK:
-	 * Basically, the Intel documentation here is poor.  It appears that
-	 * you need to set the bit to be able to access the coprocessor from
-	 * SVC mode.  Whether that allows access from user space or not is
-	 * unclear.
-	 */
-	asm volatile (
-		"mrc p15, 0, %0, c15, c1, 0\n\t"
-		"orr %0, %0, %1\n\t"
-		"mcr p15, 0, %0, c15, c1, 0\n\t"
-		/* The action is delayed, so we have to do this: */
-		"mrc p15, 0, %0, c15, c1, 0\n\t"
-		"mov %0, %0\n\t"
-		"sub pc, pc, #4"
-		: "=r" (tmp) : "i" (1 << 6) );
-
-	intctl_write0(0);		// disable all interrupts
-    	intctl_write1(0);
-	intstr_write0(0);		// treat all as IRQ
-    	intstr_write1(0);
-	if(machine_is_iq80331()) 	// all interrupts are inputs to chip
-		*IOP331_PCIIRSR = 0x0f;
-
-	for(i = IOP331_IRQ_OFS; i < NR_IOP331_IRQS; i++)
-	{
-		set_irq_chip(i, (i < 32) ? &iop331_irqchip1 : &iop331_irqchip2);
-		set_irq_handler(i, do_level_IRQ);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
-}
-
diff --git a/arch/arm/mach-iop3xx/iop331-pci.c b/arch/arm/mach-iop3xx/iop331-pci.c
deleted file mode 100644
index 44dd213..0000000
--- a/arch/arm/mach-iop3xx/iop331-pci.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop331-pci.c
- *
- * PCI support for the Intel IOP331 chipset
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2003, 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/hardware.h>
-#include <asm/mach/pci.h>
-
-#include <asm/arch/iop331.h>
-
-#undef DEBUG
-#undef DEBUG1
-
-#ifdef DEBUG
-#define  DBG(x...) printk(x)
-#else
-#define  DBG(x...) do { } while (0)
-#endif
-
-#ifdef DEBUG1
-#define  DBG1(x...) printk(x)
-#else
-#define  DBG1(x...) do { } while (0)
-#endif
-
-/*
- * This routine builds either a type0 or type1 configuration command.  If the
- * bus is on the 80331 then a type0 made, else a type1 is created.
- */
-static u32 iop331_cfg_address(struct pci_bus *bus, int devfn, int where)
-{
-	struct pci_sys_data *sys = bus->sysdata;
-	u32 addr;
-
-	if (sys->busnr == bus->number)
-		addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
-	else
-		addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
-
-	addr |=	PCI_FUNC(devfn) << 8 | (where & ~3);
-
-	return addr;
-}
-
-/*
- * This routine checks the status of the last configuration cycle.  If an error
- * was detected it returns a 1, else it returns a 0.  The errors being checked
- * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
- * the discovery stage.
- */
-static int iop331_pci_status(void)
-{
-	unsigned int status;
-	int ret = 0;
-
-	/*
-	 * Check the status registers.
-	 */
-	status = *IOP331_ATUSR;
-	if (status & 0xf900)
-	{
-		DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
-		*IOP331_ATUSR = status & 0xf900;
-		ret = 1;
-	}
-	status = *IOP331_ATUISR;
-	if (status & 0x679f)
-	{
-		DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
-		*IOP331_ATUISR = status & 0x679f;
-		ret = 1;
-	}
-	return ret;
-}
-
-/*
- * Simply write the address register and read the configuration
- * data.  Note that the 4 nop's ensure that we are able to handle
- * a delayed abort (in theory.)
- */
-static inline u32 iop331_read(unsigned long addr)
-{
-	u32 val;
-
-	__asm__ __volatile__(
-		"str	%1, [%2]\n\t"
-		"ldr	%0, [%3]\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		: "=r" (val)
-		: "r" (addr), "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
-
-	return val;
-}
-
-/*
- * The read routines must check the error status of the last configuration
- * cycle.  If there was an error, the routine returns all hex f's.
- */
-static int
-iop331_read_config(struct pci_bus *bus, unsigned int devfn, int where,
-		int size, u32 *value)
-{
-	unsigned long addr = iop331_cfg_address(bus, devfn, where);
-	u32 val = iop331_read(addr) >> ((where & 3) * 8);
-
-	if( iop331_pci_status() )
-		val = 0xffffffff;
-
-	*value = val;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop331_write_config(struct pci_bus *bus, unsigned int devfn, int where,
-		int size, u32 value)
-{
-	unsigned long addr = iop331_cfg_address(bus, devfn, where);
-	u32 val;
-
-	if (size != 4) {
-		val = iop331_read(addr);
-		if (!iop331_pci_status() == 0)
-			return PCIBIOS_SUCCESSFUL;
-
-		where = (where & 3) * 8;
-
-		if (size == 1)
-			val &= ~(0xff << where);
-		else
-			val &= ~(0xffff << where);
-
-		*IOP331_OCCDR = val | value << where;
-	} else {
-		asm volatile(
-			"str	%1, [%2]\n\t"
-			"str	%0, [%3]\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			:
-			: "r" (value), "r" (addr),
-			  "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop331_ops = {
-	.read	= iop331_read_config,
-	.write	= iop331_write_config,
-};
-
-/*
- * When a PCI device does not exist during config cycles, the XScale gets a
- * bus error instead of returning 0xffffffff. This handler simply returns.
- */
-int
-iop331_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
-	DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
-		addr, fsr, regs->ARM_pc, regs->ARM_lr);
-
-	/*
-	 * If it was an imprecise abort, then we need to correct the
-	 * return address to be _after_ the instruction.
-	 */
-	if (fsr & (1 << 10))
-		regs->ARM_pc += 4;
-
-	return 0;
-}
-
-/*
- * Scan an IOP331 PCI bus.  sys->bus defines which bus we scan.
- */
-struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	return pci_scan_bus(sys->busnr, &iop331_ops, sys);
-}
-
-void iop331_init(void)
-{
-	DBG1("PCI:  Intel 80331 PCI init code.\n");
-	DBG1("\tATU: IOP331_ATUCMD=0x%04x\n", *IOP331_ATUCMD);
-	DBG1("\tATU: IOP331_OMWTVR0=0x%04x, IOP331_OIOWTVR=0x%04x\n",
-			*IOP331_OMWTVR0,
-			*IOP331_OIOWTVR);
-	DBG1("\tATU: IOP331_OMWTVR1=0x%04x\n", *IOP331_OMWTVR1);
-	DBG1("\tATU: IOP331_ATUCR=0x%08x\n", *IOP331_ATUCR);
-	DBG1("\tATU: IOP331_IABAR0=0x%08x IOP331_IALR0=0x%08x IOP331_IATVR0=%08x\n", *IOP331_IABAR0, *IOP331_IALR0, *IOP331_IATVR0);
-	DBG1("\tATU: IOP31_IABAR1=0x%08x IOP331_IALR1=0x%08x\n", *IOP331_IABAR1, *IOP331_IALR1);
-	DBG1("\tATU: IOP331_ERBAR=0x%08x IOP331_ERLR=0x%08x IOP331_ERTVR=%08x\n", *IOP331_ERBAR, *IOP331_ERLR, *IOP331_ERTVR);
-	DBG1("\tATU: IOP331_IABAR2=0x%08x IOP331_IALR2=0x%08x IOP331_IATVR2=%08x\n", *IOP331_IABAR2, *IOP331_IALR2, *IOP331_IATVR2);
-	DBG1("\tATU: IOP331_IABAR3=0x%08x IOP331_IALR3=0x%08x IOP331_IATVR3=%08x\n", *IOP331_IABAR3, *IOP331_IALR3, *IOP331_IATVR3);
-
-	hook_fault_code(16+6, iop331_pci_abort, SIGBUS, "imprecise external abort");
-}
-
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
deleted file mode 100644
index 3cc98d8..0000000
--- a/arch/arm/mach-iop3xx/iop331-setup.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop331-setup.c
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2004 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#define IOP331_UART_XTAL 33334000
-
-/*
- * Standard IO mapping for all IOP331 based systems
- */
-static struct map_desc iop331_std_desc[] __initdata = {
-	{	/* mem mapped registers */
-		.virtual	= IOP331_VIRT_MEM_BASE,
-		.pfn		= __phys_to_pfn(IOP331_PHYS_MEM_BASE),
-		.length		= 0x00002000,
-		.type		= MT_DEVICE
-	}, {	/* PCI IO space */
-		.virtual	= IOP331_PCI_LOWER_IO_VA,
-		.pfn		= __phys_to_pfn(IOP331_PCI_LOWER_IO_PA),
-		.length		= IOP331_PCI_IO_WINDOW_SIZE,
-		.type		= MT_DEVICE
-	}
-};
-
-static struct resource iop33x_uart0_resources[] = {
-	[0] = {
-		.start = IOP331_UART0_PHYS,
-		.end = IOP331_UART0_PHYS + 0x3f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IOP331_UART0,
-		.end = IRQ_IOP331_UART0,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-static struct resource iop33x_uart1_resources[] = {
-	[0] = {
-		.start = IOP331_UART1_PHYS,
-		.end = IOP331_UART1_PHYS + 0x3f,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IOP331_UART1,
-		.end = IRQ_IOP331_UART1,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-static struct plat_serial8250_port iop33x_uart0_data[] = {
-	{
-       .membase     = (char*)(IOP331_UART0_VIRT),
-       .mapbase     = (IOP331_UART0_PHYS),
-       .irq         = IRQ_IOP331_UART0,
-       .uartclk     = IOP331_UART_XTAL,
-       .regshift    = 2,
-       .iotype      = UPIO_MEM,
-       .flags       = UPF_SKIP_TEST,
-	},
-	{  },
-};
-
-static struct plat_serial8250_port iop33x_uart1_data[] = {
-	{
-       .membase     = (char*)(IOP331_UART1_VIRT),
-       .mapbase     = (IOP331_UART1_PHYS),
-       .irq         = IRQ_IOP331_UART1,
-       .uartclk     = IOP331_UART_XTAL,
-       .regshift    = 2,
-       .iotype      = UPIO_MEM,
-       .flags       = UPF_SKIP_TEST,
-	},
-	{  },
-};
-
-static struct platform_device iop33x_uart0 = {
-       .name = "serial8250",
-       .id = PLAT8250_DEV_PLATFORM,
-       .dev.platform_data = iop33x_uart0_data,
-       .num_resources = 2,
-       .resource = iop33x_uart0_resources,
-};
-
-static struct platform_device iop33x_uart1 = {
-       .name = "serial8250",
-       .id = PLAT8250_DEV_PLATFORM1,
-       .dev.platform_data = iop33x_uart1_data,
-       .num_resources = 2,
-       .resource = iop33x_uart1_resources,
-};
-
-static struct resource iop33x_i2c_0_resources[] = {
-	[0] = {
-		.start = 0xfffff680,
-		.end = 0xfffff698,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IOP331_I2C_0,
-		.end = IRQ_IOP331_I2C_0,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-static struct resource iop33x_i2c_1_resources[] = {
-	[0] = {
-		.start = 0xfffff6a0,
-		.end = 0xfffff6b8,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_IOP331_I2C_1,
-		.end = IRQ_IOP331_I2C_1,
-		.flags = IORESOURCE_IRQ
-	}
-};
-
-static struct platform_device iop33x_i2c_0_controller = {
-	.name = "IOP3xx-I2C",
-	.id = 0,
-	.num_resources = 2,
-	.resource = iop33x_i2c_0_resources
-};
-
-static struct platform_device iop33x_i2c_1_controller = {
-	.name = "IOP3xx-I2C",
-	.id = 1,
-	.num_resources = 2,
-	.resource = iop33x_i2c_1_resources
-};
-
-static struct platform_device *iop33x_devices[] __initdata = {
-	&iop33x_uart0,
-	&iop33x_uart1,
-	&iop33x_i2c_0_controller,
-	&iop33x_i2c_1_controller
-};
-
-void __init iop33x_init(void)
-{
-	if(iop_is_331())
-	{
-		platform_add_devices(iop33x_devices,
-				ARRAY_SIZE(iop33x_devices));
-	}
-}
-
-void __init iop331_map_io(void)
-{
-	iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
-}
-
-#ifdef CONFIG_ARCH_IOP331
-extern void iop331_init_irq(void);
-extern struct sys_timer iop331_timer;
-#endif
-
-#ifdef CONFIG_ARCH_IQ80331
-extern void iq80331_map_io(void);
-#endif
-
-#ifdef CONFIG_MACH_IQ80332
-extern void iq80332_map_io(void);
-#endif
-
-#if defined(CONFIG_ARCH_IQ80331)
-MACHINE_START(IQ80331, "Intel IQ80331")
-	/* Maintainer: Intel Corp. */
-	.phys_io	= 0xfefff000,
-	.io_pg_offst	= ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
-	.map_io		= iq80331_map_io,
-	.init_irq	= iop331_init_irq,
-	.timer		= &iop331_timer,
-	.boot_params	= 0x0100,
-	.init_machine	= iop33x_init,
-MACHINE_END
-
-#elif defined(CONFIG_MACH_IQ80332)
-MACHINE_START(IQ80332, "Intel IQ80332")
-	/* Maintainer: Intel Corp. */
-	.phys_io	= 0xfefff000,
-	.io_pg_offst	= ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
-	.map_io		= iq80332_map_io,
-	.init_irq	= iop331_init_irq,
-	.timer		= &iop331_timer,
-	.boot_params	= 0x0100,
-	.init_machine	= iop33x_init,
-MACHINE_END
-
-#else
-#error No machine descriptor defined for this IOP3XX implementation
-#endif
-
-
diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c
deleted file mode 100644
index 0c09e74..0000000
--- a/arch/arm/mach-iop3xx/iop331-time.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop331-time.c
- *
- * Timer code for IOP331 based systems
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- *
- * Copyright 2003 Intel Corp.
- *
- *  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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-static inline unsigned long get_elapsed(void)
-{
-	return LATCH - *IOP331_TU_TCR0;
-}
-
-static unsigned long iop331_gettimeoffset(void)
-{
-	unsigned long elapsed, usec;
-	u32 tisr1, tisr2;
-
-	/*
-	 * If an interrupt was pending before we read the timer,
-	 * we've already wrapped.  Factor this into the time.
-	 * If an interrupt was pending after we read the timer,
-	 * it may have wrapped between checking the interrupt
-	 * status and reading the timer.  Re-read the timer to
-	 * be sure its value is after the wrap.
-	 */
-
-	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
-	elapsed = get_elapsed();
-	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
-
-	if(tisr1 & 1)
-		elapsed += LATCH;
-	else if (tisr2 & 1)
-		elapsed = LATCH + get_elapsed();
-
-	/*
-	 * Now convert them to usec.
-	 */
-	usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
-
-	return usec;
-}
-
-static irqreturn_t
-iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	u32 tisr;
-
-	write_seqlock(&xtime_lock);
-
-	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
-	tisr |= 1;
-	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
-
-	timer_tick(regs);
-
-	write_sequnlock(&xtime_lock);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction iop331_timer_irq = {
-	.name		= "IOP331 Timer Tick",
-	.handler	= iop331_timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-};
-
-static void __init iop331_timer_init(void)
-{
-	u32 timer_ctl;
-
-	setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq);
-
-	timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD |
-			IOP331_TMR_RATIO_1_1;
-
-	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
-
-	asm volatile("mcr p6, 0, %0, c0, c1, 0"	: : "r" (timer_ctl));
-
-}
-
-struct sys_timer iop331_timer = {
-	.init		= iop331_timer_init,
-	.offset		= iop331_gettimeoffset,
-};
diff --git a/arch/arm/mach-iop3xx/iq31244-mm.c b/arch/arm/mach-iop3xx/iq31244-mm.c
deleted file mode 100644
index e874b54..0000000
--- a/arch/arm/mach-iop3xx/iq31244-mm.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80321 platform
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * 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/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80321 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-static struct map_desc iq31244_io_desc[] __initdata = {
-	{	/* on-board devices */
-		.virtual	= IQ31244_UART,
-		.pfn		= __phys_to_pfn(IQ31244_UART),
-		.length		= 0x00100000,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init iq31244_map_io(void)
-{
-	iop321_map_io();
-
-	iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
-}
diff --git a/arch/arm/mach-iop3xx/iq31244-pci.c b/arch/arm/mach-iop3xx/iq31244-pci.c
deleted file mode 100644
index f3c6413..0000000
--- a/arch/arm/mach-iop3xx/iq31244-pci.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80321-pci.c
- *
- * PCI support for the Intel IQ80321 reference board
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)	\
-({ int _ctl_ = -1;				\
-   unsigned int _idsel = idsel - minid;		\
-   if (_idsel <= maxid)				\
-      _ctl_ = pci_irq_table[_idsel][pin-1];	\
-   _ctl_; })
-
-#define INTA	IRQ_IQ31244_INTA
-#define INTB	IRQ_IQ31244_INTB
-#define INTC	IRQ_IQ31244_INTC
-#define INTD	IRQ_IQ31244_INTD
-
-#define INTE	IRQ_IQ31244_I82546
-
-static inline int __init
-iq31244_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-	static int pci_irq_table[][4] = {
-		/*
-		 * PCI IDSEL/INTPIN->INTLINE
-		 * A       B       C       D
-		 */
-#ifdef CONFIG_ARCH_EP80219
-		{INTB, INTB, INTB, INTB}, /* CFlash */
-		{INTE, INTE, INTE, INTE}, /* 82551 Pro 100 */
-		{INTD, INTD, INTD, INTD}, /* PCI-X Slot */
-		{INTC, INTC, INTC, INTC}, /* SATA   */
-#else
-		{INTB, INTB, INTB, INTB}, /* CFlash */
-		{INTC, INTC, INTC, INTC}, /* SATA   */
-		{INTD, INTD, INTD, INTD}, /* PCI-X Slot */
-		{INTE, INTE, INTE, INTE}, /* 82546 GigE */
-#endif // CONFIG_ARCH_EP80219
-	};
-
-	BUG_ON(pin < 1 || pin > 4);
-
-	return PCI_IRQ_TABLE_LOOKUP(0, 7);
-}
-
-static int iq31244_setup(int nr, struct pci_sys_data *sys)
-{
-	struct resource *res;
-
-	if(nr != 0)
-		return 0;
-
-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-	if (!res)
-		panic("PCI: unable to alloc resources");
-
-	res[0].start = IOP321_PCI_LOWER_IO_VA;
-	res[0].end   = IOP321_PCI_UPPER_IO_VA;
-	res[0].name  = "IQ31244 PCI I/O Space";
-	res[0].flags = IORESOURCE_IO;
-
-	res[1].start = IOP321_PCI_LOWER_MEM_PA;
-	res[1].end   = IOP321_PCI_UPPER_MEM_PA;
-	res[1].name  = "IQ31244 PCI Memory Space";
-	res[1].flags = IORESOURCE_MEM;
-
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
-
-	sys->mem_offset = IOP321_PCI_MEM_OFFSET;
-	sys->io_offset  = IOP321_PCI_IO_OFFSET;
-
-	sys->resource[0] = &res[0];
-	sys->resource[1] = &res[1];
-	sys->resource[2] = NULL;
-
-	return 1;
-}
-
-static void iq31244_preinit(void)
-{
-	iop321_init();
-}
-
-static struct hw_pci iq31244_pci __initdata = {
-	.swizzle	= pci_std_swizzle,
-	.nr_controllers = 1,
-	.setup		= iq31244_setup,
-	.scan		= iop321_scan_bus,
-	.preinit	= iq31244_preinit,
-	.map_irq	= iq31244_map_irq
-};
-
-static int __init iq31244_pci_init(void)
-{
-	if (machine_is_iq31244())
-		pci_common_init(&iq31244_pci);
-	return 0;
-}
-
-subsys_initcall(iq31244_pci_init);
-
-
-
-
diff --git a/arch/arm/mach-iop3xx/iq80321-mm.c b/arch/arm/mach-iop3xx/iq80321-mm.c
deleted file mode 100644
index d9cac5e..0000000
--- a/arch/arm/mach-iop3xx/iq80321-mm.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80321 platform
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * 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/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80321 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-static struct map_desc iq80321_io_desc[] __initdata = {
- 	{	/* on-board devices */
-		.virtual	= IQ80321_UART,
-		.pfn		= __phys_to_pfn(IQ80321_UART),
-		.length		= 0x00100000,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init iq80321_map_io(void)
-{
-	iop321_map_io();
-
-	iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
-}
diff --git a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c
deleted file mode 100644
index d9758d3..0000000
--- a/arch/arm/mach-iop3xx/iq80321-pci.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80321-pci.c
- *
- * PCI support for the Intel IQ80321 reference board
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)	\
-({ int _ctl_ = -1;				\
-   unsigned int _idsel = idsel - minid;		\
-   if (_idsel <= maxid)				\
-      _ctl_ = pci_irq_table[_idsel][pin-1];	\
-   _ctl_; })
-
-#define INTA	IRQ_IQ80321_INTA
-#define INTB	IRQ_IQ80321_INTB
-#define INTC	IRQ_IQ80321_INTC
-#define INTD	IRQ_IQ80321_INTD
-
-#define INTE	IRQ_IQ80321_I82544
-
-static inline int __init
-iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-	static int pci_irq_table[][4] = {
-		/*
-		 * PCI IDSEL/INTPIN->INTLINE
-		 * A       B       C       D
-		 */
-		{INTE, INTE, INTE, INTE}, /* Gig-E */
-		{-1, -1, -1, -1}, 	  /* Unused */
-		{INTC, INTD, INTA, INTB}, /* PCI-X Slot */
-		{-1, -1, -1, -1},
-	};
-
-	BUG_ON(pin < 1 || pin > 4);
-
-//	return PCI_IRQ_TABLE_LOOKUP(4, 7);
-	return pci_irq_table[idsel%4][pin-1];
-}
-
-static int iq80321_setup(int nr, struct pci_sys_data *sys)
-{
-	struct resource *res;
-
-	if(nr != 0)
-		return 0;
-
-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-	if (!res)
-		panic("PCI: unable to alloc resources");
-
-	res[0].start = IOP321_PCI_LOWER_IO_VA;
-	res[0].end   = IOP321_PCI_UPPER_IO_VA;
-	res[0].name  = "IQ80321 PCI I/O Space";
-	res[0].flags = IORESOURCE_IO;
-
-	res[1].start = IOP321_PCI_LOWER_MEM_PA;
-	res[1].end   = IOP321_PCI_UPPER_MEM_PA;
-	res[1].name  = "IQ80321 PCI Memory Space";
-	res[1].flags = IORESOURCE_MEM;
-
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
-
-	sys->mem_offset = IOP321_PCI_MEM_OFFSET;
-	sys->io_offset  = IOP321_PCI_IO_OFFSET;
-
-	sys->resource[0] = &res[0];
-	sys->resource[1] = &res[1];
-	sys->resource[2] = NULL;
-
-	return 1;
-}
-
-static void iq80321_preinit(void)
-{
-	iop321_init();
-}
-
-static struct hw_pci iq80321_pci __initdata = {
-	.swizzle	= pci_std_swizzle,
-	.nr_controllers = 1,
-	.setup		= iq80321_setup,
-	.scan		= iop321_scan_bus,
-	.preinit	= iq80321_preinit,
-	.map_irq	= iq80321_map_irq
-};
-
-static int __init iq80321_pci_init(void)
-{
-	if (machine_is_iq80321())
-		pci_common_init(&iq80321_pci);
-	return 0;
-}
-
-subsys_initcall(iq80321_pci_init);
-
-
-
-
diff --git a/arch/arm/mach-iop3xx/iq80331-mm.c b/arch/arm/mach-iop3xx/iq80331-mm.c
deleted file mode 100644
index 129eb49..0000000
--- a/arch/arm/mach-iop3xx/iq80331-mm.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80331 platform
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003 Intel Corp.
- *
- * 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/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80331 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-
-void __init iq80331_map_io(void)
-{
-	iop331_map_io();
-}
diff --git a/arch/arm/mach-iop3xx/iq80331-pci.c b/arch/arm/mach-iop3xx/iq80331-pci.c
deleted file mode 100644
index 40d8610..0000000
--- a/arch/arm/mach-iop3xx/iq80331-pci.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80331-pci.c
- *
- * PCI support for the Intel IQ80331 reference board
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003, 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)	\
-({ int _ctl_ = -1;				\
-   unsigned int _idsel = idsel - minid;		\
-   if (_idsel <= maxid)				\
-      _ctl_ = pci_irq_table[_idsel][pin-1];	\
-   _ctl_; })
-
-#define INTA	IRQ_IQ80331_INTA
-#define INTB	IRQ_IQ80331_INTB
-#define INTC	IRQ_IQ80331_INTC
-#define INTD	IRQ_IQ80331_INTD
-
-//#define INTE	IRQ_IQ80331_I82544
-
-static inline int __init
-iq80331_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-	static int pci_irq_table[][4] = {
-		/*
-		 * PCI IDSEL/INTPIN->INTLINE
-		 * A       B       C       D
-		 */
-		{INTB, INTC, INTD, INTA}, /* PCI-X Slot */
-		{INTC, INTC, INTC, INTC}, /* GigE  */
-	};
-
-	BUG_ON(pin < 1 || pin > 4);
-
-	return PCI_IRQ_TABLE_LOOKUP(1, 7);
-}
-
-static int iq80331_setup(int nr, struct pci_sys_data *sys)
-{
-	struct resource *res;
-
-	if(nr != 0)
-		return 0;
-
-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-	if (!res)
-		panic("PCI: unable to alloc resources");
-
-	res[0].start = IOP331_PCI_LOWER_IO_VA;
-	res[0].end   = IOP331_PCI_UPPER_IO_VA;
-	res[0].name  = "IQ80331 PCI I/O Space";
-	res[0].flags = IORESOURCE_IO;
-
-	res[1].start = IOP331_PCI_LOWER_MEM_PA;
-	res[1].end   = IOP331_PCI_UPPER_MEM_PA;
-	res[1].name  = "IQ80331 PCI Memory Space";
-	res[1].flags = IORESOURCE_MEM;
-
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
-
-	sys->mem_offset = IOP331_PCI_MEM_OFFSET;
-	sys->io_offset  = IOP331_PCI_IO_OFFSET;
-
-	sys->resource[0] = &res[0];
-	sys->resource[1] = &res[1];
-	sys->resource[2] = NULL;
-
-	return 1;
-}
-
-static void iq80331_preinit(void)
-{
-	iop331_init();
-}
-
-static struct hw_pci iq80331_pci __initdata = {
-	.swizzle	= pci_std_swizzle,
-	.nr_controllers = 1,
-	.setup		= iq80331_setup,
-	.scan		= iop331_scan_bus,
-	.preinit	= iq80331_preinit,
-	.map_irq	= iq80331_map_irq
-};
-
-static int __init iq80331_pci_init(void)
-{
-	if (machine_is_iq80331())
-		pci_common_init(&iq80331_pci);
-	return 0;
-}
-
-subsys_initcall(iq80331_pci_init);
-
-
-
-
diff --git a/arch/arm/mach-iop3xx/iq80332-mm.c b/arch/arm/mach-iop3xx/iq80332-mm.c
deleted file mode 100644
index 2feaf75..0000000
--- a/arch/arm/mach-iop3xx/iq80332-mm.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80332 platform
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2004 Intel Corp.
- *
- * 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/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80332 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-
-void __init iq80332_map_io(void)
-{
-	iop331_map_io();
-}
diff --git a/arch/arm/mach-iop3xx/iq80332-pci.c b/arch/arm/mach-iop3xx/iq80332-pci.c
deleted file mode 100644
index afc0676..0000000
--- a/arch/arm/mach-iop3xx/iq80332-pci.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80332-pci.c
- *
- * PCI support for the Intel IQ80332 reference board
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)	\
-({ int _ctl_ = -1;				\
-   unsigned int _idsel = idsel - minid;		\
-   if (_idsel <= maxid)				\
-      _ctl_ = pci_irq_table[_idsel][pin-1];	\
-   _ctl_; })
-
-#define INTA	IRQ_IQ80332_INTA
-#define INTB	IRQ_IQ80332_INTB
-#define INTC	IRQ_IQ80332_INTC
-#define INTD	IRQ_IQ80332_INTD
-
-//#define INTE	IRQ_IQ80332_I82544
-
-static inline int __init
-iq80332_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-	static int pci_irq_table[][8] = {
-		/*
-		 * PCI IDSEL/INTPIN->INTLINE
-		 * A       B       C       D
-		 */
-		{-1,   -1,   -1,   -1},
-		{-1,   -1,   -1,   -1},
-		{-1,   -1,   -1,   -1},
-		{INTA, INTB, INTC, INTD}, /* PCI-X Slot */
-		{-1,   -1,   -1,   -1},
-		{INTC, INTC, INTC, INTC}, /* GigE  */
-		{-1,   -1,   -1,   -1},
-		{-1,   -1,   -1,   -1},
-	};
-
-	BUG_ON(pin < 1 || pin > 4);
-
-	return PCI_IRQ_TABLE_LOOKUP(1, 7);
-}
-
-static int iq80332_setup(int nr, struct pci_sys_data *sys)
-{
-	struct resource *res;
-
-	if(nr != 0)
-		return 0;
-
-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-	if (!res)
-		panic("PCI: unable to alloc resources");
-
-	res[0].start = IOP331_PCI_LOWER_IO_VA;
-	res[0].end   = IOP331_PCI_UPPER_IO_VA;
-	res[0].name  = "IQ80332 PCI I/O Space";
-	res[0].flags = IORESOURCE_IO;
-
-	res[1].start = IOP331_PCI_LOWER_MEM_PA;
-	res[1].end   = IOP331_PCI_UPPER_MEM_PA;
-	res[1].name  = "IQ80332 PCI Memory Space";
-	res[1].flags = IORESOURCE_MEM;
-
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
-
-	sys->mem_offset = IOP331_PCI_MEM_OFFSET;
-	sys->io_offset  = IOP331_PCI_IO_OFFSET;
-
-	sys->resource[0] = &res[0];
-	sys->resource[1] = &res[1];
-	sys->resource[2] = NULL;
-
-	return 1;
-}
-
-static void iq80332_preinit(void)
-{
-	iop331_init();
-}
-
-static struct hw_pci iq80332_pci __initdata = {
-	.swizzle	= pci_std_swizzle,
-	.nr_controllers = 1,
-	.setup		= iq80332_setup,
-	.scan		= iop331_scan_bus,
-	.preinit	= iq80332_preinit,
-	.map_irq	= iq80332_map_irq
-};
-
-static int __init iq80332_pci_init(void)
-{
-	if (machine_is_iq80332())
-		pci_common_init(&iq80332_pci);
-	return 0;
-}
-
-subsys_initcall(iq80332_pci_init);
-
-
-
-
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 7c25dbd..35dd8b3 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -26,6 +26,7 @@
 #include <linux/bitops.h>
 #include <linux/time.h>
 #include <linux/timex.h>
+#include <linux/clocksource.h>
 
 #include <asm/hardware.h>
 #include <asm/uaccess.h>
@@ -255,16 +256,6 @@
 
 #define CLOCK_TICKS_PER_USEC	((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
 
-/* IRQs are disabled before entering here from do_gettimeofday() */
-static unsigned long ixp4xx_gettimeoffset(void)
-{
-	u32 elapsed;
-
-	elapsed = *IXP4XX_OSTS - last_jiffy_time;
-
-	return elapsed / CLOCK_TICKS_PER_USEC;
-}
-
 static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	write_seqlock(&xtime_lock);
@@ -309,7 +300,6 @@
 
 struct sys_timer ixp4xx_timer = {
 	.init		= ixp4xx_timer_init,
-	.offset		= ixp4xx_gettimeoffset,
 };
 
 static struct resource ixp46x_i2c_resources[] = {
@@ -365,3 +355,29 @@
 			ixp4xx_exp_bus_size >> 20);
 }
 
+cycle_t ixp4xx_get_cycles(void)
+{
+	return *IXP4XX_OSTS;
+}
+
+static struct clocksource clocksource_ixp4xx = {
+	.name 		= "OSTS",
+	.rating		= 200,
+	.read		= ixp4xx_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift 		= 20,
+	.is_continuous 	= 1,
+};
+
+unsigned long ixp4xx_timer_freq = FREQ;
+static int __init ixp4xx_clocksource_init(void)
+{
+	clocksource_ixp4xx.mult =
+		clocksource_hz2mult(ixp4xx_timer_freq,
+				    clocksource_ixp4xx.shift);
+	clocksource_register(&clocksource_ixp4xx);
+
+	return 0;
+}
+
+device_initcall(ixp4xx_clocksource_init);
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 749a337..162c266 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -159,6 +159,8 @@
 
 static void __init nslu2_init(void)
 {
+	ixp4xx_timer_freq = NSLU2_FREQ;
+
 	ixp4xx_sys_init();
 
 	nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index c753a3c..62e42c7a 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -172,9 +172,11 @@
 };
 
 static struct omap_kp_platform_data kp_data = {
-	.rows	= 8,
-	.cols	= 8,
-	.keymap = fsample_keymap,
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= fsample_keymap,
+	.keymapsize	= ARRAY_SIZE(fsample_keymap),
+	.delay		= 4,
 };
 
 static struct platform_device kp_device = {
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index cd3a06d..6e11307 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -167,10 +167,13 @@
 };
 
 static struct omap_kp_platform_data h2_kp_data = {
-	.rows	= 8,
-	.cols	= 8,
-	.keymap = h2_keymap,
-	.rep	= 1,
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= h2_keymap,
+	.keymapsize	= ARRAY_SIZE(h2_keymap),
+	.rep		= 1,
+	.delay		= 9,
+	.dbounce	= 1,
 };
 
 static struct platform_device h2_kp_device = {
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 7b20611..f225a08 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -247,10 +247,13 @@
 };
 
 static struct omap_kp_platform_data h3_kp_data = {
-	.rows	= 8,
-	.cols	= 8,
-	.keymap = h3_keymap,
-	.rep	= 1,
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= h3_keymap,
+	.keymapsize	= ARRAY_SIZE(h3_keymap),
+	.rep		= 1,
+	.delay		= 9,
+	.dbounce	= 1,
 };
 
 static struct platform_device h3_kp_device = {
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 4cbc62d..cb00530 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -159,9 +159,11 @@
 };
 
 static struct omap_kp_platform_data innovator_kp_data = {
-	.rows	= 8,
-	.cols	= 8,
-	.keymap = innovator_keymap,
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= innovator_keymap,
+	.keymapsize	= ARRAY_SIZE(innovator_keymap),
+	.delay		= 4,
 };
 
 static struct platform_device innovator_kp_device = {
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 02b980d..dbc555d 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -71,9 +71,11 @@
 };
 
 static struct omap_kp_platform_data nokia770_kp_data = {
-	.rows   = 8,
-	.cols   = 8,
-	.keymap = nokia770_keymap
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= nokia770_keymap,
+	.keymapsize	= ARRAY_SIZE(nokia770_keymap)
+	.delay		= 4,
 };
 
 static struct platform_device nokia770_kp_device = {
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index b742261..6b05647 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -266,9 +266,11 @@
 };
 
 static struct omap_kp_platform_data osk_kp_data = {
-	.rows	= 8,
-	.cols	= 8,
-	.keymap = (int *) osk_keymap,
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= (int *) osk_keymap,
+	.keymapsize	= ARRAY_SIZE(osk_keymap),
+	.delay		= 9,
 };
 
 static struct resource osk5912_kp_resources[] = {
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 64b45d8..fa4be96 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -171,9 +171,12 @@
 };
 
 static struct omap_kp_platform_data kp_data = {
-	.rows	= 8,
-	.cols	= 8,
-	.keymap = p2_keymap,
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= p2_keymap,
+	.keymapsize	= ARRAY_SIZE(p2_keymap),
+	.delay		= 4,
+	.dbounce	= 1,
 };
 
 static struct platform_device kp_device = {
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index f1958e8..638490e 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 
 #include <asm/io.h>
+#include <asm/mach-types.h>
 
 #include <asm/arch/cpu.h>
 #include <asm/arch/usb.h>
@@ -586,77 +587,53 @@
  *-------------------------------------------------------------------------*/
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
-/*
- * Resets some clocks that may be left on from bootloader,
- * but leaves serial clocks on. See also omap_late_clk_reset().
- */
-static inline void omap1_early_clk_reset(void)
-{
-	//omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
-}
 
-static int __init omap1_late_clk_reset(void)
+static void __init omap1_clk_disable_unused(struct clk *clk)
 {
-	/* Turn off all unused clocks */
-	struct clk *p;
 	__u32 regval32;
 
-	/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
-	regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
-	omap_writew(regval32, SOFT_REQ_REG);
-	omap_writew(0, SOFT_REQ_REG2);
-
-	list_for_each_entry(p, &clocks, node) {
-		if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) ||
-			p->enable_reg == 0)
-			continue;
-
-		/* Clocks in the DSP domain need api_ck. Just assume bootloader
-		 * has not enabled any DSP clocks */
-		if ((u32)p->enable_reg == DSP_IDLECT2) {
-			printk(KERN_INFO "Skipping reset check for DSP domain "
-			       "clock \"%s\"\n", p->name);
-			continue;
-		}
-
-		/* Is the clock already disabled? */
-		if (p->flags & ENABLE_REG_32BIT) {
-			if (p->flags & VIRTUAL_IO_ADDRESS)
-				regval32 = __raw_readl(p->enable_reg);
-			else
-				regval32 = omap_readl(p->enable_reg);
-		} else {
-			if (p->flags & VIRTUAL_IO_ADDRESS)
-				regval32 = __raw_readw(p->enable_reg);
-			else
-				regval32 = omap_readw(p->enable_reg);
-		}
-
-		if ((regval32 & (1 << p->enable_bit)) == 0)
-			continue;
-
-		/* FIXME: This clock seems to be necessary but no-one
-		 * has asked for its activation. */
-		if (p == &tc2_ck         // FIX: pm.c (SRAM), CCP, Camera
-		    || p == &ck_dpll1out.clk // FIX: SoSSI, SSR
-		    || p == &arm_gpio_ck // FIX: GPIO code for 1510
-		    ) {
-			printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
-			       p->name);
-			continue;
-		}
-
-		printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name);
-		p->disable(p);
-		printk(" done\n");
+	/* Clocks in the DSP domain need api_ck. Just assume bootloader
+	 * has not enabled any DSP clocks */
+	if ((u32)clk->enable_reg == DSP_IDLECT2) {
+		printk(KERN_INFO "Skipping reset check for DSP domain "
+		       "clock \"%s\"\n", clk->name);
+		return;
 	}
 
-	return 0;
+	/* Is the clock already disabled? */
+	if (clk->flags & ENABLE_REG_32BIT) {
+		if (clk->flags & VIRTUAL_IO_ADDRESS)
+			regval32 = __raw_readl(clk->enable_reg);
+			else
+				regval32 = omap_readl(clk->enable_reg);
+	} else {
+		if (clk->flags & VIRTUAL_IO_ADDRESS)
+			regval32 = __raw_readw(clk->enable_reg);
+		else
+			regval32 = omap_readw(clk->enable_reg);
+	}
+
+	if ((regval32 & (1 << clk->enable_bit)) == 0)
+		return;
+
+	/* FIXME: This clock seems to be necessary but no-one
+	 * has asked for its activation. */
+	if (clk == &tc2_ck		// FIX: pm.c (SRAM), CCP, Camera
+	    || clk == &ck_dpll1out.clk	// FIX: SoSSI, SSR
+	    || clk == &arm_gpio_ck	// FIX: GPIO code for 1510
+		) {
+		printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
+		       clk->name);
+		return;
+	}
+
+	printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name);
+	clk->disable(clk);
+	printk(" done\n");
 }
-late_initcall(omap1_late_clk_reset);
 
 #else
-#define omap1_early_clk_reset()	{}
+#define omap1_clk_disable_unused	NULL
 #endif
 
 static struct clk_functions omap1_clk_functions = {
@@ -664,6 +641,7 @@
 	.clk_disable		= omap1_clk_disable,
 	.clk_round_rate		= omap1_clk_round_rate,
 	.clk_set_rate		= omap1_clk_set_rate,
+	.clk_disable_unused	= omap1_clk_disable_unused,
 };
 
 int __init omap1_clk_init(void)
@@ -671,8 +649,13 @@
 	struct clk ** clkp;
 	const struct omap_clock_config *info;
 	int crystal_type = 0; /* Default 12 MHz */
+	u32 reg;
 
-	omap1_early_clk_reset();
+	/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
+	reg = omap_readw(SOFT_REQ_REG) & (1 << 4);
+	omap_writew(reg, SOFT_REQ_REG);
+	omap_writew(0, SOFT_REQ_REG2);
+
 	clk_init(&omap1_clk_functions);
 
 	/* By default all idlect1 clocks are allowed to idle */
@@ -772,6 +755,12 @@
 	omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
 #endif
 
+	/* Amstrad Delta wants BCLK high when inactive */
+	if (machine_is_ams_delta())
+		omap_writel(omap_readl(ULPD_CLOCK_CTRL) |
+				(1 << SDW_MCLK_INV_BIT),
+				ULPD_CLOCK_CTRL);
+
 	/* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
 	/* (on 730, bit 13 must not be cleared) */
 	if (cpu_is_omap730())
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index b7c6881..f7df002 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -89,6 +89,7 @@
 #define EN_DSPTIMCK	5
 
 /* Various register defines for clock controls scattered around OMAP chip */
+#define SDW_MCLK_INV_BIT	2	/* In ULPD_CLKC_CTRL */
 #define USB_MCLK_EN_BIT		4	/* In ULPD_CLKC_CTRL */
 #define USB_HOST_HHC_UHOST_EN	9	/* In MOD_CONF_CTRL_0 */
 #define SWD_ULPD_PLL_CLK_REQ	1	/* In SWD_CLK_DIV_CTRL_SEL */
@@ -741,6 +742,18 @@
 	.disable	= &omap1_clk_disable_generic,
 };
 
+static struct clk i2c_ick = {
+	.name		= "i2c_ick",
+	.id		= 1,
+	.flags		= CLOCK_IN_OMAP16XX |
+			  VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+			  ALWAYS_ENABLED,
+	.parent		= &armper_ck.clk,
+	.recalc		= &followparent_recalc,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
+};
+
 static struct clk * onchip_clks[] = {
 	/* non-ULPD clocks */
 	&ck_ref,
@@ -790,6 +803,7 @@
 	/* Virtual clocks */
 	&virtual_ck_mpu,
 	&i2c_fck,
+	&i2c_ick,
 };
 
 #endif
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index fa74ef7..5432335 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -199,6 +199,17 @@
 MUX_CFG("P15_1610_UWIRE_CS3",	 8,   12,    1,	  1,  22,   0,	  1,	 1,  1)
 MUX_CFG("N15_1610_UWIRE_CS1",	 7,   18,    2,	  1,  14,   0,	 NA,	 0,  1)
 
+/* OMAP-1610 SPI */
+MUX_CFG("U19_1610_SPIF_SCK",	 7,    21,   6,	  1,  15,   0,	  1,	 1,  1)
+MUX_CFG("U18_1610_SPIF_DIN",	 8,    0,    6,	  1,  18,   1,	  1,	 0,  1)
+MUX_CFG("P20_1610_SPIF_DIN",	 6,    27,   4,   1,   7,   1,    1,     0,  1)
+MUX_CFG("W21_1610_SPIF_DOUT",	 8,    3,    6,	  1,  19,   0,	  1,	 0,  1)
+MUX_CFG("R18_1610_SPIF_DOUT",	 7,    9,    3,	  1,  11,   0,	  1,	 0,  1)
+MUX_CFG("N14_1610_SPIF_CS0",	 8,    9,    6,	  1,  21,   0,	  1,	 1,  1)
+MUX_CFG("N15_1610_SPIF_CS1",	 7,    18,   6,	  1,  14,   0,	  1,	 1,  1)
+MUX_CFG("T19_1610_SPIF_CS2",	 7,    15,   4,	  1,  13,   0,	  1,	 1,  1)
+MUX_CFG("P15_1610_SPIF_CS3",	 8,    12,   3,	  1,  22,   0,	  1,	 1,  1)
+
 /* OMAP-1610 Flash */
 MUX_CFG("L3_1610_FLASH_CS2B_OE",10,    6,    1,	 NA,   0,   0,	 NA,	 0,  1)
 MUX_CFG("M8_1610_FLASH_CS2B_WE",10,    3,    1,	 NA,   0,   0,	 NA,	 0,  1)
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 7993b7b..2db6b73 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -166,8 +166,8 @@
 
 static struct omap_mmc_config apollon_mmc_config __initdata = {
 	.mmc [0] = {
-		.enabled 	= 0,
-		.wire4		= 0,
+		.enabled 	= 1,
+		.wire4		= 1,
 		.wp_pin		= -1,
 		.power_pin	= -1,
 		.switch_pin	= -1,
@@ -257,6 +257,9 @@
 	/* REVISIT: where's the correct place */
 	omap_cfg_reg(W19_24XX_SYS_NIRQ);
 
+	/* Use Interal loop-back in MMC/SDIO Module Input Clock selection */
+	CONTROL_DEVCONF |= (1 << 24);
+
 	/*
  	 * Make sure the serial ports are muxed on at this point.
 	 * You have to mux them off in device drivers later on
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 4933fce..996aeda 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -245,6 +245,7 @@
 	.rows		= 6,
 	.cols		= 7,
 	.keymap 	= h4_keymap,
+	.keymapsize 	= ARRAY_SIZE(h4_keymap),
 	.rep		= 1,
 	.row_gpios 	= row_gpios,
 	.col_gpios 	= col_gpios,
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index d1b648a..0de201c 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -32,10 +32,14 @@
 #include "memory.h"
 #include "clock.h"
 
+#undef DEBUG
+
 //#define DOWN_VARIABLE_DPLL 1			/* Experimental */
 
 static struct prcm_config *curr_prcm_set;
 static u32 curr_perf_level = PRCM_FULL_SPEED;
+static struct clk *vclk;
+static struct clk *sclk;
 
 /*-------------------------------------------------------------------------
  * Omap2 specific clock functions
@@ -79,6 +83,14 @@
 	propagate_rate(clk);
 }
 
+static void omap2_set_osc_ck(int enable)
+{
+	if (enable)
+		PRCM_CLKSRC_CTRL &= ~(0x3 << 3);
+	else
+		PRCM_CLKSRC_CTRL |= 0x3 << 3;
+}
+
 /* Enable an APLL if off */
 static void omap2_clk_fixed_enable(struct clk *clk)
 {
@@ -101,14 +113,56 @@
 	else if (clk == &apll54_ck)
 		cval = (1 << 6);
 
-	while (!CM_IDLEST_CKGEN & cval) {		/* Wait for lock */
+	while (!(CM_IDLEST_CKGEN & cval)) {		/* Wait for lock */
 		++i;
 		udelay(1);
-		if (i == 100000)
+		if (i == 100000) {
+			printk(KERN_ERR "Clock %s didn't lock\n", clk->name);
 			break;
+		}
 	}
 }
 
+static void omap2_clk_wait_ready(struct clk *clk)
+{
+	unsigned long reg, other_reg, st_reg;
+	u32 bit;
+	int i;
+
+	reg = (unsigned long) clk->enable_reg;
+	if (reg == (unsigned long) &CM_FCLKEN1_CORE ||
+	    reg == (unsigned long) &CM_FCLKEN2_CORE)
+		other_reg = (reg & ~0xf0) | 0x10;
+	else if (reg == (unsigned long) &CM_ICLKEN1_CORE ||
+		 reg == (unsigned long) &CM_ICLKEN2_CORE)
+		other_reg = (reg & ~0xf0) | 0x00;
+	else
+		return;
+
+	/* No check for DSS or cam clocks */
+	if ((reg & 0x0f) == 0) {
+		if (clk->enable_bit <= 1 || clk->enable_bit == 31)
+			return;
+	}
+
+	/* Check if both functional and interface clocks
+	 * are running. */
+	bit = 1 << clk->enable_bit;
+	if (!(__raw_readl(other_reg) & bit))
+		return;
+	st_reg = (other_reg & ~0xf0) | 0x20;
+	i = 0;
+	while (!(__raw_readl(st_reg) & bit)) {
+		i++;
+		if (i == 100000) {
+			printk(KERN_ERR "Timeout enabling clock %s\n", clk->name);
+			break;
+		}
+	}
+	if (i)
+		pr_debug("Clock %s stable after %d loops\n", clk->name, i);
+}
+
 /* Enables clock without considering parent dependencies or use count
  * REVISIT: Maybe change this to use clk->enable like on omap1?
  */
@@ -119,6 +173,11 @@
 	if (clk->flags & ALWAYS_ENABLED)
 		return 0;
 
+	if (unlikely(clk == &osc_ck)) {
+		omap2_set_osc_ck(1);
+		return 0;
+	}
+
 	if (unlikely(clk->enable_reg == 0)) {
 		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
 		       clk->name);
@@ -133,6 +192,9 @@
 	regval32 = __raw_readl(clk->enable_reg);
 	regval32 |= (1 << clk->enable_bit);
 	__raw_writel(regval32, clk->enable_reg);
+	wmb();
+
+	omap2_clk_wait_ready(clk);
 
 	return 0;
 }
@@ -155,6 +217,11 @@
 {
 	u32 regval32;
 
+	if (unlikely(clk == &osc_ck)) {
+		omap2_set_osc_ck(0);
+		return;
+	}
+
 	if (clk->enable_reg == 0)
 		return;
 
@@ -166,6 +233,7 @@
 	regval32 = __raw_readl(clk->enable_reg);
 	regval32 &= ~(1 << clk->enable_bit);
 	__raw_writel(regval32, clk->enable_reg);
+	wmb();
 }
 
 static int omap2_clk_enable(struct clk *clk)
@@ -695,12 +763,14 @@
 		reg_val = __raw_readl(reg);
 		reg_val &= ~(field_mask << div_off);
 		reg_val |= (field_val << div_off);
-
 		__raw_writel(reg_val, reg);
+		wmb();
 		clk->rate = clk->parent->rate / field_val;
 
-		if (clk->flags & DELAYED_APP)
+		if (clk->flags & DELAYED_APP) {
 			__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+			wmb();
+		}
 		ret = 0;
 	} else if (clk->set_rate != 0)
 		ret = clk->set_rate(clk, rate);
@@ -836,10 +906,12 @@
 		reg_val = __raw_readl(reg) & ~(field_mask << src_off);
 		reg_val |= (field_val << src_off);
 		__raw_writel(reg_val, reg);
+		wmb();
 
-		if (clk->flags & DELAYED_APP)
+		if (clk->flags & DELAYED_APP) {
 			__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
-
+			wmb();
+		}
 		if (clk->usecount > 0)
 			_omap2_clk_enable(clk);
 
@@ -953,12 +1025,29 @@
  * Omap2 clock reset and init functions
  *-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+static void __init omap2_clk_disable_unused(struct clk *clk)
+{
+	u32 regval32;
+
+	regval32 = __raw_readl(clk->enable_reg);
+	if ((regval32 & (1 << clk->enable_bit)) == 0)
+		return;
+
+	printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
+	_omap2_clk_disable(clk);
+}
+#else
+#define omap2_clk_disable_unused	NULL
+#endif
+
 static struct clk_functions omap2_clk_functions = {
 	.clk_enable		= omap2_clk_enable,
 	.clk_disable		= omap2_clk_disable,
 	.clk_round_rate		= omap2_clk_round_rate,
 	.clk_set_rate		= omap2_clk_set_rate,
 	.clk_set_parent		= omap2_clk_set_parent,
+	.clk_disable_unused	= omap2_clk_disable_unused,
 };
 
 static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
@@ -984,27 +1073,19 @@
 	sys->rate = sclk;
 }
 
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-static void __init omap2_disable_unused_clocks(void)
+/*
+ * Set clocks for bypass mode for reboot to work.
+ */
+void omap2_clk_prepare_for_reboot(void)
 {
-	struct clk *ck;
-	u32 regval32;
+	u32 rate;
 
-	list_for_each_entry(ck, &clocks, node) {
-		if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
-			ck->enable_reg == 0)
-			continue;
+	if (vclk == NULL || sclk == NULL)
+		return;
 
-		regval32 = __raw_readl(ck->enable_reg);
-		if ((regval32 & (1 << ck->enable_bit)) == 0)
-			continue;
-
-		printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
-		_omap2_clk_disable(ck);
-	}
+	rate = clk_get_rate(sclk);
+	clk_set_rate(vclk, rate);
 }
-late_initcall(omap2_disable_unused_clocks);
-#endif
 
 /*
  * Switch the MPU rate if specified on cmdline.
@@ -1077,8 +1158,27 @@
 	 */
 	clk_enable(&sync_32k_ick);
 	clk_enable(&omapctrl_ick);
+
+	/* Force the APLLs active during bootup to avoid disabling and
+	 * enabling them unnecessarily. */
+	clk_enable(&apll96_ck);
+	clk_enable(&apll54_ck);
+
 	if (cpu_is_omap2430())
 		clk_enable(&sdrc_ick);
 
+	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
+	vclk = clk_get(NULL, "virt_prcm_set");
+	sclk = clk_get(NULL, "sys_ck");
+
 	return 0;
 }
+
+static int __init omap2_disable_aplls(void)
+{
+	clk_disable(&apll96_ck);
+	clk_disable(&apll54_ck);
+
+	return 0;
+}
+late_initcall(omap2_disable_aplls);
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 2781dfb..8816f5a 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -560,7 +560,7 @@
 	.name		= "osc_ck",
 	.rate		= 26000000,		/* fixed up in clock init */
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+				RATE_FIXED | RATE_PROPAGATES,
 };
 
 /* With out modem likely 12MHz, with modem likely 13MHz */
@@ -1368,7 +1368,8 @@
 };
 
 static struct clk mcspi1_ick = {
-	.name		= "mcspi1_ick",
+	.name		= "mcspi_ick",
+	.id		= 1,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1377,7 +1378,8 @@
 };
 
 static struct clk mcspi1_fck = {
-	.name		= "mcspi1_fck",
+	.name		= "mcspi_fck",
+	.id		= 1,
 	.parent		= &func_48m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1386,7 +1388,8 @@
 };
 
 static struct clk mcspi2_ick = {
-	.name		= "mcspi2_ick",
+	.name		= "mcspi_ick",
+	.id		= 2,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1395,7 +1398,8 @@
 };
 
 static struct clk mcspi2_fck = {
-	.name		= "mcspi2_fck",
+	.name		= "mcspi_fck",
+	.id		= 2,
 	.parent		= &func_48m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1404,7 +1408,8 @@
 };
 
 static struct clk mcspi3_ick = {
-	.name		= "mcspi3_ick",
+	.name		= "mcspi_ick",
+	.id		= 3,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
@@ -1413,7 +1418,8 @@
 };
 
 static struct clk mcspi3_fck = {
-	.name		= "mcspi3_fck",
+	.name		= "mcspi_fck",
+	.id		= 3,
 	.parent		= &func_48m_ck,
 	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index c7a48f9..f4f04d8 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -13,6 +13,8 @@
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
 
 #include <asm/io.h>
 #include <asm/arch/gpmc.h>
@@ -41,6 +43,19 @@
 #define GPMC_CS0		0x60
 #define GPMC_CS_SIZE		0x30
 
+#define GPMC_CS_NUM		8
+#define GPMC_MEM_START		0x00000000
+#define GPMC_MEM_END		0x3FFFFFFF
+#define BOOT_ROM_SPACE		0x100000	/* 1MB */
+
+#define GPMC_CHUNK_SHIFT	24		/* 16 MB */
+#define GPMC_SECTION_SHIFT	28		/* 128 MB */
+
+static struct resource	gpmc_mem_root;
+static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
+static spinlock_t	gpmc_mem_lock = SPIN_LOCK_UNLOCKED;
+static unsigned		gpmc_cs_map;
+
 static void __iomem *gpmc_base =
 	(void __iomem *) IO_ADDRESS(GPMC_BASE);
 static void __iomem *gpmc_cs_base =
@@ -187,9 +202,168 @@
 	return 0;
 }
 
-unsigned long gpmc_cs_get_base_addr(int cs)
+static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
 {
-	return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24;
+	u32 l;
+	u32 mask;
+
+	mask = (1 << GPMC_SECTION_SHIFT) - size;
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+	l &= ~0x3f;
+	l = (base >> GPMC_CHUNK_SHIFT) & 0x3f;
+	l &= ~(0x0f << 8);
+	l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
+	l |= 1 << 6;		/* CSVALID */
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_disable_mem(int cs)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+	l &= ~(1 << 6);		/* CSVALID */
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+{
+	u32 l;
+	u32 mask;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+	*base = (l & 0x3f) << GPMC_CHUNK_SHIFT;
+	mask = (l >> 8) & 0x0f;
+	*size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT);
+}
+
+static int gpmc_cs_mem_enabled(int cs)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+	return l & (1 << 6);
+}
+
+static void gpmc_cs_set_reserved(int cs, int reserved)
+{
+	gpmc_cs_map &= ~(1 << cs);
+	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+}
+
+static int gpmc_cs_reserved(int cs)
+{
+	return gpmc_cs_map & (1 << cs);
+}
+
+static unsigned long gpmc_mem_align(unsigned long size)
+{
+	int order;
+
+	size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1);
+	order = GPMC_CHUNK_SHIFT - 1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	size = 1 << order;
+	return size;
+}
+
+static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+{
+	struct resource	*res = &gpmc_cs_mem[cs];
+	int r;
+
+	size = gpmc_mem_align(size);
+	spin_lock(&gpmc_mem_lock);
+	res->start = base;
+	res->end = base + size - 1;
+	r = request_resource(&gpmc_mem_root, res);
+	spin_unlock(&gpmc_mem_lock);
+
+	return r;
+}
+
+int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
+{
+	struct resource *res = &gpmc_cs_mem[cs];
+	int r = -1;
+
+	if (cs > GPMC_CS_NUM)
+		return -ENODEV;
+
+	size = gpmc_mem_align(size);
+	if (size > (1 << GPMC_SECTION_SHIFT))
+		return -ENOMEM;
+
+	spin_lock(&gpmc_mem_lock);
+	if (gpmc_cs_reserved(cs)) {
+		r = -EBUSY;
+		goto out;
+	}
+	if (gpmc_cs_mem_enabled(cs))
+		r = adjust_resource(res, res->start & ~(size - 1), size);
+	if (r < 0)
+		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+				      size, NULL, NULL);
+	if (r < 0)
+		goto out;
+
+	gpmc_cs_enable_mem(cs, res->start, res->end - res->start + 1);
+	*base = res->start;
+	gpmc_cs_set_reserved(cs, 1);
+out:
+	spin_unlock(&gpmc_mem_lock);
+	return r;
+}
+
+void gpmc_cs_free(int cs)
+{
+	spin_lock(&gpmc_mem_lock);
+	if (cs >= GPMC_CS_NUM || !gpmc_cs_reserved(cs)) {
+		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
+		BUG();
+		spin_unlock(&gpmc_mem_lock);
+		return;
+	}
+	gpmc_cs_disable_mem(cs);
+	release_resource(&gpmc_cs_mem[cs]);
+	gpmc_cs_set_reserved(cs, 0);
+	spin_unlock(&gpmc_mem_lock);
+}
+
+void __init gpmc_mem_init(void)
+{
+	int cs;
+	unsigned long boot_rom_space = 0;
+
+	if (cpu_is_omap242x()) {
+		u32 l;
+		l = omap_readl(OMAP242X_CONTROL_STATUS);
+		/* In case of internal boot the 1st MB is redirected to the
+		 * boot ROM memory space.
+		 */
+		if (l & (1 << 3))
+			boot_rom_space = BOOT_ROM_SPACE;
+	} else
+		/* We assume internal boot if the mode can't be
+		 * determined.
+		 */
+		boot_rom_space = BOOT_ROM_SPACE;
+	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
+	gpmc_mem_root.end = GPMC_MEM_END;
+
+	/* Reserve all regions that has been set up by bootloader */
+	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+		u32 base, size;
+
+		if (!gpmc_cs_mem_enabled(cs))
+			continue;
+		gpmc_cs_get_memconf(cs, &base, &size);
+		if (gpmc_cs_insert_mem(cs, base, size) < 0)
+			BUG();
+	}
 }
 
 void __init gpmc_init(void)
@@ -206,4 +380,6 @@
 	l &= 0x03 << 3;
 	l |= (0x02 << 3) | (1 << 0);
 	gpmc_write_reg(GPMC_SYSCONFIG, l);
+
+	gpmc_mem_init();
 }
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index dfc3b35..1ed2fff 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -41,18 +41,6 @@
 		.nr_irqs	= 96,
 	}, {
 		/* XXX: DSP INTC */
-
-#if 0
-	/*
-	 * Commented out for now until we fix the IVA clocking
-	 */
-#ifdef CONFIG_ARCH_OMAP2420
-	}, {
-		/* IVA INTC (2420 only) */
-		.base_reg	= OMAP24XX_IVA_INTC_BASE,
-		.nr_irqs	= 16,	/* Actually 32, but only 16 are used */
-#endif
-#endif
 	}
 };
 
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 60ef084..f538d0f 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -104,6 +104,20 @@
 MUX_CFG_24XX("K15_24XX_UART3_TX",	0x118,	0,	0,	0,	1)
 MUX_CFG_24XX("K14_24XX_UART3_RX",	0x119,	0,	0,	0,	1)
 
+/* MMC/SDIO */
+MUX_CFG_24XX("G19_24XX_MMC_CLKO",	0x0f3,	0,	0,	0,	1)
+MUX_CFG_24XX("H18_24XX_MMC_CMD",	0x0f4,	0,	0,	0,	1)
+MUX_CFG_24XX("F20_24XX_MMC_DAT0",	0x0f5,	0,	0,	0,	1)
+MUX_CFG_24XX("H14_24XX_MMC_DAT1",	0x0f6,	0,	0,	0,	1)
+MUX_CFG_24XX("E19_24XX_MMC_DAT2",	0x0f7,	0,	0,	0,	1)
+MUX_CFG_24XX("D19_24XX_MMC_DAT3",	0x0f8,	0,	0,	0,	1)
+MUX_CFG_24XX("F19_24XX_MMC_DAT_DIR0",	0x0f9,	0,	0,	0,	1)
+MUX_CFG_24XX("E20_24XX_MMC_DAT_DIR1",	0x0fa,	0,	0,	0,	1)
+MUX_CFG_24XX("F18_24XX_MMC_DAT_DIR2",	0x0fb,	0,	0,	0,	1)
+MUX_CFG_24XX("E18_24XX_MMC_DAT_DIR3",	0x0fc,	0,	0,	0,	1)
+MUX_CFG_24XX("G18_24XX_MMC_CMD_DIR",	0x0fd,	0,	0,	0,	1)
+MUX_CFG_24XX("H15_24XX_MMC_CLKI",	0x0fe,	0,	0,	0,	1)
+
 /* Keypad GPIO*/
 MUX_CFG_24XX("T19_24XX_KBR0",		0x106,	3,	1,	1,	1)
 MUX_CFG_24XX("R19_24XX_KBR1",		0x107,	3,	1,	1,	1)
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index c2bf57e..90f5305 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -19,6 +19,8 @@
 
 #include "prcm-regs.h"
 
+extern void omap2_clk_prepare_for_reboot(void);
+
 u32 omap_prcm_get_reset_sources(void)
 {
 	return RM_RSTST_WKUP & 0x7f;
@@ -28,12 +30,6 @@
 /* Resets clock rates and reboots the system. Only called from system.h */
 void omap_prcm_arch_reset(char mode)
 {
-	u32 rate;
-	struct clk *vclk, *sclk;
-
-	vclk = clk_get(NULL, "virt_prcm_set");
-	sclk = clk_get(NULL, "sys_ck");
-	rate = clk_get_rate(sclk);
-	clk_set_rate(vclk, rate);	/* go to bypass for OMAP limitation */
+	omap2_clk_prepare_for_reboot();
 	RM_RSTCTRL_WKUP |= 2;
 }
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index cce2657..337c01c 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -284,21 +284,9 @@
 /*
  * USB Device Controller
  */
-static void corgi_udc_command(int cmd)
-{
-	switch(cmd)	{
-	case PXA2XX_UDC_CMD_CONNECT:
-		GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
-		break;
-	case PXA2XX_UDC_CMD_DISCONNECT:
-		GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
-		break;
-	}
-}
-
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
 	/* no connect GPIO; corgi can't tell connection status */
-	.udc_command		= corgi_udc_command,
+	.gpio_pullup		= CORGI_GPIO_USB_PULLUP,
 };
 
 
@@ -350,7 +338,6 @@
 	corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
 
 	pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
-	pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
 	pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
 
  	pxa_set_udc_info(&udc_info);
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index bbd138b..df37594 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -2,6 +2,13 @@
 
 menu "S3C24XX Implementations"
 
+config MACH_AML_M5900
+	bool "AML M5900 Series"
+	select CPU_S3C2410
+	help
+	   Say Y here if you are using the American Microsystems M5900 Series
+           <http://www.amltd.com>
+
 config MACH_ANUBIS
 	bool "Simtec Electronics ANUBIS"
 	select CPU_S3C2440
@@ -126,6 +133,12 @@
 	help
  	  Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
 
+config MACH_VSTMS
+	bool "VMSTMS"
+	select CPU_S3C2412
+	help
+	  Say Y here if you are using an VSTMS board
+
 endmenu
 
 config S3C2410_CLOCK
@@ -133,10 +146,24 @@
 	help
 	  Clock code for the S3C2410, and similar processors
 
+config S3C2410_PM
+	bool
+	depends on CONFIG_PM
+	help
+	  Power Management code common to S3C2410 and better
+
+config CPU_S3C2410_DMA
+	bool
+	depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
+	default y if CPU_S3C2410 || CPU_S3C2442
+	help
+	  DMA device selection for S3C2410 and compatible CPUs
+
 config CPU_S3C2410
 	bool
 	depends on ARCH_S3C2410
 	select S3C2410_CLOCK
+	select S3C2410_PM
 	help
 	  Support for S3C2410 and S3C2410A family from the S3C24XX line
 	  of Samsung Mobile CPUs.
@@ -149,6 +176,13 @@
 		   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
 	default y if CPU_S3C2412
 
+config S3C2412_PM
+	bool
+	default y if PM
+	depends on CPU_S3C2412
+	help
+	  Internal config node to apply S3C2412 power management
+
 config CPU_S3C2412
 	bool
 	depends on ARCH_S3C2410
@@ -165,6 +199,7 @@
 	bool
 	depends on ARCH_S3C2410
 	select S3C2410_CLOCK
+	select S3C2410_PM
 	select CPU_S3C244X
 	help
 	  Support for S3C2440 Samsung Mobile CPU based systems.
@@ -173,6 +208,7 @@
 	bool
 	depends on ARCH_S3C2420
 	select S3C2410_CLOCK
+	select S3C2410_PM
 	select CPU_S3C244X
 	help
 	  Support for S3C2442 Samsung Mobile CPU based systems.
@@ -256,7 +292,7 @@
 
 config PM_SIMTEC
 	bool
-	depends on PM && (ARCH_BAST || MACH_VR1000)
+	depends on PM && (ARCH_BAST || MACH_VR1000 || MACH_AML_M5900)
 	default y
 
 config S3C2410_LOWLEVEL_UART_PORT
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 0eadec9..d660133 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -9,6 +9,8 @@
 obj-m			:=
 obj-n			:=
 obj-			:=
+obj-dma-y		:=
+obj-dma-n		:=
 
 # DMA
 obj-$(CONFIG_S3C2410_DMA)	+= dma.o
@@ -20,6 +22,10 @@
 
 obj-$(CONFIG_CPU_S3C2410)	+= s3c2410.o
 obj-$(CONFIG_CPU_S3C2410)	+= s3c2410-gpio.o
+obj-$(CONFIG_CPU_S3C2410)	+= s3c2410-irq.o
+
+obj-$(CONFIG_S3C2410_PM)	+= s3c2410-pm.o s3c2410-sleep.o
+obj-$(CONFIG_CPU_S3C2410_DMA)	+= s3c2410-dma.o
 
 # Power Management support
 
@@ -30,6 +36,9 @@
 obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
 obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-irq.o
 obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-clock.o
+obj-dma-$(CONFIG_CPU_S3C2412)	+= s3c2412-dma.o
+
+obj-$(CONFIG_S3C2412_PM)	+= s3c2412-pm.o
 
 #
 # S3C244X support
@@ -47,6 +56,7 @@
 obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-irq.o
 obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-clock.o
 obj-$(CONFIG_CPU_S3C2440)	+= s3c2410-gpio.o
+obj-dma-$(CONFIG_CPU_S3C2440)	+= s3c2440-dma.o
 
 # S3C2442 support
 
@@ -57,8 +67,13 @@
 
 obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
 
+# merge in dma objects
+
+obj-y				+= $(obj-dma-y)
+
 # machine specific support
 
+obj-$(CONFIG_MACH_AML_M5900)	+= mach-amlm5900.o
 obj-$(CONFIG_MACH_ANUBIS)	+= mach-anubis.o
 obj-$(CONFIG_MACH_OSIRIS)	+= mach-osiris.o
 obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
@@ -71,5 +86,6 @@
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
 obj-$(CONFIG_MACH_OTOM)		+= mach-otom.o
 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
 
 obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
\ No newline at end of file
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index def4441..440e9aa 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -18,10 +18,6 @@
  * 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
- *
- * Modifications:
- *     08-Jan-2003 BJD  Moved from central IRQ code
- *     21-Aug-2005 BJD  Fixed missing code and compile errors
 */
 
 
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
index 1c3c6ad..9d4899e 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/mach-s3c2410/cpu.c
@@ -124,6 +124,15 @@
 		.init		= s3c2412_init,
 		.name		= name_s3c2412,
 	},
+	{			/* a newer version of the s3c2412 */
+		.idcode		= 0x32412003,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2412_map_io,
+		.init_clocks	= s3c2412_init_clocks,
+		.init_uarts	= s3c2412_init_uarts,
+		.init		= s3c2412_init,
+		.name		= name_s3c2412,
+	},
 	{
 		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
 		.idmask		= 0xffffffff,
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
index 726e2eaf..14fb0ba 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/arch/arm/mach-s3c2410/devs.h
@@ -8,11 +8,6 @@
  * 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.
- *
- * Modifications:
- *      18-Aug-2004 BJD  Created initial version
- *	27-Aug-2004 BJD  Added timers 0 through 3
- *	10-Feb-2005 BJD	 Added camera from guillaume.gourat@nexvision.tv
 */
 #include <linux/platform_device.h>
 
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index cc92a7b..d264bbb 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1,35 +1,16 @@
-/* linux/arch/arm/mach-bast/dma.c
+/* linux/arch/arm/mach-s3c2410/dma.c
  *
- * (c) 2003-2005 Simtec Electronics
+ * (c) 2003-2005,2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * S3C2410 DMA core
  *
- * http://www.simtec.co.uk/products/EB2410ITX/
+ * http://armlinux.simtec.co.uk/
  *
  * 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.
- *
- * Changelog:
- *  27-Feb-2005 BJD  Added kmem cache for dma descriptors
- *  18-Nov-2004 BJD  Removed error for loading onto stopped channel
- *  10-Nov-2004 BJD  Ensure all external symbols exported for modules
- *  10-Nov-2004 BJD  Use sys_device and sysdev_class for power management
- *  08-Aug-2004 BJD  Apply rmk's suggestions
- *  21-Jul-2004 BJD  Ported to linux 2.6
- *  12-Jul-2004 BJD  Finished re-write and change of API
- *  06-Jul-2004 BJD  Rewrote dma code to try and cope with various problems
- *  23-May-2003 BJD  Created file
- *  19-Aug-2003 BJD  Cleanup, header fix, added URL
- *
- * This file is based on the Sangwook Lee/Samsung patches, re-written due
- * to various ommisions from the code (such as flexible dma configuration)
- * for use with the BAST system board.
- *
- * The re-write is pretty much complete, and should be good enough for any
- * possible DMA function
- */
+*/
 
 
 #ifdef CONFIG_S3C2410_DMA_DEBUG
@@ -55,10 +36,14 @@
 #include <asm/mach/dma.h>
 #include <asm/arch/map.h>
 
+#include "dma.h"
+
 /* io map for dma */
 static void __iomem *dma_base;
 static kmem_cache_t *dma_kmem;
 
+struct s3c24xx_dma_selection dma_sel;
+
 /* dma channel state information */
 struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
 
@@ -79,7 +64,6 @@
 	pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
 	writel(val, dma_regaddr(chan, reg));
 }
-
 #endif
 
 #define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
@@ -151,12 +135,20 @@
 #define dbg_showchan(chan) do { } while(0)
 #endif /* CONFIG_S3C2410_DMA_DEBUG */
 
-#define check_channel(chan) \
-  do { if ((chan) >= S3C2410_DMA_CHANNELS) { \
-    printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \
-    return -EINVAL; \
-  } } while(0)
+static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
 
+/* lookup_dma_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
+{
+	if (channel & DMACH_LOW_LEVEL)
+		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+	else
+		return dma_chan_map[channel];
+}
 
 /* s3c2410_dma_stats_timeout
  *
@@ -321,8 +313,10 @@
 s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
 		     enum s3c2410_dma_buffresult result)
 {
+#if 0
 	pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
 		 chan->callback_fn, buf, buf->id, buf->size, result);
+#endif
 
 	if (chan->callback_fn != NULL) {
 		(chan->callback_fn)(chan, buf->id, buf->size, result);
@@ -439,7 +433,6 @@
 	return 0;
 }
 
-
 /* s3c2410_dma_enqueue
  *
  * queue an given buffer for dma transfer.
@@ -460,11 +453,12 @@
 int s3c2410_dma_enqueue(unsigned int channel, void *id,
 			dma_addr_t data, int size)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 	struct s3c2410_dma_buf *buf;
 	unsigned long flags;
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	pr_debug("%s: id=%p, data=%08x, size=%d\n",
 		 __FUNCTION__, id, (unsigned int)data, size);
@@ -562,8 +556,10 @@
 static inline void
 s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
 {
+#if 0
 	pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
 		 chan->number, chan->load_state);
+#endif
 
 	switch (chan->load_state) {
 	case S3C2410_DMALOAD_NONE:
@@ -718,7 +714,8 @@
 		if (chan->load_state == S3C2410_DMALOAD_NONE) {
 			pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
 				 chan->number, jiffies);
-			s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+			s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
+					 S3C2410_DMAOP_STOP);
 		}
 	}
 
@@ -726,37 +723,34 @@
 	return IRQ_HANDLED;
 }
 
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
+
 /* s3c2410_request_dma
  *
  * get control of an dma channel
 */
 
-int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client,
+int s3c2410_dma_request(unsigned int channel,
+			struct s3c2410_dma_client *client,
 			void *dev)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan;
 	unsigned long flags;
 	int err;
 
 	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
 		 channel, client->name, dev);
 
-	check_channel(channel);
-
 	local_irq_save(flags);
 
-	dbg_showchan(chan);
-
-	if (chan->in_use) {
-		if (client != chan->client) {
-			printk(KERN_ERR "dma%d: already in use\n", channel);
-			local_irq_restore(flags);
-			return -EBUSY;
-		} else {
-			printk(KERN_ERR "dma%d: client already has channel\n", channel);
-		}
+	chan = s3c2410_dma_map_channel(channel);
+	if (chan == NULL) {
+		local_irq_restore(flags);
+		return -EBUSY;
 	}
 
+	dbg_showchan(chan);
+
 	chan->client = client;
 	chan->in_use = 1;
 
@@ -809,14 +803,14 @@
 
 int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 	unsigned long flags;
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	local_irq_save(flags);
 
-
 	if (chan->client != client) {
 		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
 		       channel, chan->client, client);
@@ -837,8 +831,12 @@
 
 	if (chan->irq_claimed)
 		free_irq(chan->irq, (void *)chan);
+
 	chan->irq_claimed = 0;
 
+	if (!(channel & DMACH_LOW_LEVEL))
+		dma_chan_map[channel] = NULL;
+
 	local_irq_restore(flags);
 
 	return 0;
@@ -848,8 +846,8 @@
 
 static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
 {
-	unsigned long tmp;
 	unsigned long flags;
+	unsigned long tmp;
 
 	pr_debug("%s:\n", __FUNCTION__);
 
@@ -997,9 +995,10 @@
 int
 s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	switch (op) {
 	case S3C2410_DMAOP_START:
@@ -1046,12 +1045,19 @@
 		       int xferunit,
 		       int dcon)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
 	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
 		 __FUNCTION__, channel, xferunit, dcon);
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
+
+	printk("Initial dcon is %08x\n", dcon);
+
+	dcon |= chan->dcon & dma_sel.dcon_mask;
+
+	printk("New dcon is %08x\n", dcon);
 
 	switch (xferunit) {
 	case 1:
@@ -1086,9 +1092,10 @@
 
 int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
 
@@ -1106,9 +1113,10 @@
 
 int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
 
@@ -1121,9 +1129,10 @@
 
 int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
 
@@ -1153,9 +1162,10 @@
 			  int hwcfg,
 			  unsigned long devaddr)
 {
-	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
 		 __FUNCTION__, (int)source, hwcfg, devaddr);
@@ -1200,9 +1210,10 @@
 
 int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
 {
- 	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+ 	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
- 	check_channel(channel);
+	if (chan == NULL)
+		return -EINVAL;
 
 	if (src != NULL)
  		*src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
@@ -1252,7 +1263,7 @@
 #define s3c2410_dma_resume  NULL
 #endif /* CONFIG_PM */
 
-static struct sysdev_class dma_sysclass = {
+struct sysdev_class dma_sysclass = {
 	set_kset_name("s3c24xx-dma"),
 	.suspend	= s3c2410_dma_suspend,
 	.resume		= s3c2410_dma_resume,
@@ -1265,7 +1276,6 @@
 	memset(p, 0, sizeof(struct s3c2410_dma_buf));
 }
 
-
 /* initialisation code */
 
 static int __init s3c2410_init_dma(void)
@@ -1274,7 +1284,7 @@
 	int channel;
 	int ret;
 
-	printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
+	printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
 
 	dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
 	if (dma_base == NULL) {
@@ -1282,6 +1292,8 @@
 		return -ENOMEM;
 	}
 
+	printk("Registering sysclass\n");
+
 	ret = sysdev_class_register(&dma_sysclass);
 	if (ret != 0) {
 		printk(KERN_ERR "dma sysclass registration failed\n");
@@ -1335,4 +1347,95 @@
 	return ret;
 }
 
-__initcall(s3c2410_init_dma);
+core_initcall(s3c2410_init_dma);
+
+static inline int is_channel_valid(unsigned int channel)
+{
+	return (channel & DMA_CH_VALID);
+}
+
+/* s3c2410_dma_map_channel()
+ *
+ * turn the virtual channel number into a real, and un-used hardware
+ * channel.
+ *
+ * currently this code uses first-free channel from the specified harware
+ * map, not taking into account anything that the board setup code may
+ * have to say about the likely peripheral set to be in use.
+*/
+
+struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
+{
+	struct s3c24xx_dma_map *ch_map;
+	struct s3c2410_dma_chan *dmach;
+	int ch;
+
+	if (dma_sel.map == NULL || channel > dma_sel.map_size)
+		return NULL;
+
+	ch_map = dma_sel.map + channel;
+
+	for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
+		if (!is_channel_valid(ch_map->channels[ch]))
+			continue;
+
+		if (s3c2410_chans[ch].in_use == 0) {
+			printk("mapped channel %d to %d\n", channel, ch);
+			break;
+		}
+	}
+
+	if (ch >= S3C2410_DMA_CHANNELS)
+		return NULL;
+
+	/* update our channel mapping */
+
+	dmach = &s3c2410_chans[ch];
+	dma_chan_map[channel] = dmach;
+
+	/* select the channel */
+
+	(dma_sel.select)(dmach, ch_map);
+
+	return dmach;
+}
+
+static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
+{
+	/* show the channel configuration */
+
+	printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
+	       (is_channel_valid(map->channels[0]) ? '0' : '-'),
+	       (is_channel_valid(map->channels[1]) ? '1' : '-'),
+	       (is_channel_valid(map->channels[2]) ? '2' : '-'),
+	       (is_channel_valid(map->channels[3]) ? '3' : '-'));
+}
+
+static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
+{
+	if (1)
+		s3c24xx_dma_show_ch(map, ch);
+
+	return 0;
+}
+
+int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
+{
+	struct s3c24xx_dma_map *nmap;
+	size_t map_sz = sizeof(*nmap) * sel->map_size;
+	int ptr;
+
+	nmap = kmalloc(map_sz, GFP_KERNEL);
+	if (nmap == NULL)
+		return -ENOMEM;
+
+	memcpy(nmap, sel->map, map_sz);
+	memcpy(&dma_sel, sel, sizeof(*sel));
+
+	dma_sel.map = nmap;
+
+	for (ptr = 0; ptr < sel->map_size; ptr++)
+		s3c24xx_dma_check_entry(nmap+ptr, ptr);
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/dma.h b/arch/arm/mach-s3c2410/dma.h
new file mode 100644
index 0000000..0ebfe0a
--- /dev/null
+++ b/arch/arm/mach-s3c2410/dma.h
@@ -0,0 +1,45 @@
+/* arch/arm/mach-s3c2410/dma.h
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * 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.
+*/
+
+extern struct sysdev_class dma_sysclass;
+extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+#define DMA_CH_VALID		(1<<31)
+
+struct s3c24xx_dma_addr {
+	unsigned long		from;
+	unsigned long		to;
+};
+
+/* struct s3c24xx_dma_map
+ *
+ * this holds the mapping information for the channel selected
+ * to be connected to the specified device
+*/
+
+struct s3c24xx_dma_map {
+	const char		*name;
+	struct s3c24xx_dma_addr  hw_addr;
+
+	unsigned long		 channels[S3C2410_DMA_CHANNELS];
+};
+
+struct s3c24xx_dma_selection {
+	struct s3c24xx_dma_map	*map;
+	unsigned long		 map_size;
+	unsigned long		 dcon_mask;
+
+	void	(*select)(struct s3c2410_dma_chan *chan,
+			  struct s3c24xx_dma_map *map);
+};
+
+extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index cd39e86..db6393c 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -18,21 +18,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Changelog
- *	13-Sep-2004  BJD  Implemented change of MISCCR
- *	14-Sep-2004  BJD  Added getpin call
- *	14-Sep-2004  BJD  Fixed bug in setpin() call
- *	30-Sep-2004  BJD  Fixed cfgpin() mask bug
- *	01-Oct-2004  BJD  Added getcfg() to get pin configuration
- *	01-Oct-2004  BJD  Fixed mask bug in pullup() call
- *	01-Oct-2004  BJD  Added getirq() to turn pin into irqno
- *	04-Oct-2004  BJD  Added irq filter controls for GPIO
- *	05-Nov-2004  BJD  EXPORT_SYMBOL() added for all code
- *	13-Mar-2005  BJD  Updates for __iomem
- *	26-Oct-2005  BJD  Added generic configuration types
- *	15-Jan-2006  LCVR Added support for the S3C2400
- */
+*/
 
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index cd6139b..3e9f346 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -181,17 +181,19 @@
 }
 
 struct irqchip s3c_irq_level_chip = {
-	.ack	   = s3c_irq_maskack,
-	.mask	   = s3c_irq_mask,
-	.unmask	   = s3c_irq_unmask,
-	.set_wake	   = s3c_irq_wake
+	.name		= "s3c-level",
+	.ack		= s3c_irq_maskack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake
 };
 
 static struct irqchip s3c_irq_chip = {
-	.ack	   = s3c_irq_ack,
-	.mask	   = s3c_irq_mask,
-	.unmask	   = s3c_irq_unmask,
-	.set_wake  = s3c_irq_wake
+	.name		= "s3c",
+	.ack		= s3c_irq_ack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake
 };
 
 static void
@@ -343,19 +345,21 @@
 }
 
 static struct irqchip s3c_irqext_chip = {
-	.mask	    = s3c_irqext_mask,
-	.unmask	    = s3c_irqext_unmask,
-	.ack	    = s3c_irqext_ack,
-	.set_type    = s3c_irqext_type,
-	.set_wake    = s3c_irqext_wake
+	.name		= "s3c-ext",
+	.mask		= s3c_irqext_mask,
+	.unmask		= s3c_irqext_unmask,
+	.ack		= s3c_irqext_ack,
+	.set_type	= s3c_irqext_type,
+	.set_wake	= s3c_irqext_wake
 };
 
 static struct irqchip s3c_irq_eint0t4 = {
-	.ack	   = s3c_irq_ack,
-	.mask	   = s3c_irq_mask,
-	.unmask	   = s3c_irq_unmask,
-	.set_wake  = s3c_irq_wake,
-	.set_type  = s3c_irqext_type,
+	.name		= "s3c-ext0",
+	.ack		= s3c_irq_ack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake,
+	.set_type	= s3c_irqext_type,
 };
 
 /* mask values for the parent registers for each of the interrupt types */
@@ -387,9 +391,10 @@
 }
 
 static struct irqchip s3c_irq_uart0 = {
-	.mask	    = s3c_irq_uart0_mask,
-	.unmask	    = s3c_irq_uart0_unmask,
-	.ack	    = s3c_irq_uart0_ack,
+	.name		= "s3c-uart0",
+	.mask		= s3c_irq_uart0_mask,
+	.unmask		= s3c_irq_uart0_unmask,
+	.ack		= s3c_irq_uart0_ack,
 };
 
 /* UART1 */
@@ -413,9 +418,10 @@
 }
 
 static struct irqchip s3c_irq_uart1 = {
-	.mask	    = s3c_irq_uart1_mask,
-	.unmask	    = s3c_irq_uart1_unmask,
-	.ack	    = s3c_irq_uart1_ack,
+	.name		= "s3c-uart1",
+	.mask		= s3c_irq_uart1_mask,
+	.unmask		= s3c_irq_uart1_unmask,
+	.ack		= s3c_irq_uart1_ack,
 };
 
 /* UART2 */
@@ -439,9 +445,10 @@
 }
 
 static struct irqchip s3c_irq_uart2 = {
-	.mask	    = s3c_irq_uart2_mask,
-	.unmask	    = s3c_irq_uart2_unmask,
-	.ack	    = s3c_irq_uart2_ack,
+	.name		= "s3c-uart2",
+	.mask		= s3c_irq_uart2_mask,
+	.unmask		= s3c_irq_uart2_unmask,
+	.ack		= s3c_irq_uart2_ack,
 };
 
 /* ADC and Touchscreen */
@@ -465,9 +472,10 @@
 }
 
 static struct irqchip s3c_irq_adc = {
-	.mask	    = s3c_irq_adc_mask,
-	.unmask	    = s3c_irq_adc_unmask,
-	.ack	    = s3c_irq_adc_ack,
+	.name		= "s3c-adc",
+	.mask		= s3c_irq_adc_mask,
+	.unmask		= s3c_irq_adc_unmask,
+	.ack		= s3c_irq_adc_ack,
 };
 
 /* irq demux for adc */
@@ -569,23 +577,104 @@
 }
 
 static void
-s3c_irq_demux_extint(unsigned int irq,
-		     struct irqdesc *desc,
-		     struct pt_regs *regs)
+s3c_irq_demux_extint8(unsigned int irq,
+		      struct irqdesc *desc,
+		      struct pt_regs *regs)
 {
 	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
 	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
 
 	eintpnd &= ~eintmsk;
+	eintpnd &= ~0xff;	/* ignore lower irqs */
 
-	if (eintpnd) {
-		irq = fls(eintpnd);
-		irq += (IRQ_EINT4 - (4 + 1));
+	/* we may as well handle all the pending IRQs here */
+
+	while (eintpnd) {
+		irq = __ffs(eintpnd);
+		eintpnd &= ~(1<<irq);
+
+		irq += (IRQ_EINT4 - 4);
+		desc_handle_irq(irq, irq_desc + irq, regs);
+	}
+
+}
+
+static void
+s3c_irq_demux_extint4t7(unsigned int irq,
+			struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+	eintpnd &= 0xff;	/* only lower irqs */
+
+	/* we may as well handle all the pending IRQs here */
+
+	while (eintpnd) {
+		irq = __ffs(eintpnd);
+		eintpnd &= ~(1<<irq);
+
+		irq += (IRQ_EINT4 - 4);
 
 		desc_handle_irq(irq, irq_desc + irq, regs);
 	}
 }
 
+#ifdef CONFIG_PM
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S3C2410_INTMSK),
+	SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+static unsigned long save_extint[3];
+static unsigned long save_eintflt[4];
+static unsigned long save_eintmask;
+
+int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+	save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+	return 0;
+}
+
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		__raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		__raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+	__raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+	return 0;
+}
+
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
 /* s3c24xx_init_irq
  *
  * Initialise S3C2410 IRQ system
@@ -674,8 +763,8 @@
 
 	/* setup the cascade irq handlers */
 
-	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
-	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
+	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
 
 	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
new file mode 100644
index 0000000..ba5109a
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -0,0 +1,266 @@
+/***********************************************************************
+ *
+ * linux/arch/arm/mach-s3c2410/mach-amlm5900.c
+ *
+ * Copyright (c) 2006 American Microsystems Limited
+ *	David Anders <danders@amltd.com>
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * @History:
+ * derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ ***********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/arch/fb.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "devs.h"
+#include "cpu.h"
+
+#ifdef CONFIG_MTD_PARTITIONS
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/physmap.h>
+
+static struct resource amlm5900_nor_resource = {
+		.start = 0x00000000,
+		.end   = 0x01000000 - 1,
+		.flags = IORESOURCE_MEM,
+};
+
+
+
+static struct mtd_partition amlm5900_mtd_partitions[] = {
+	{
+		.name		= "System",
+		.size		= 0x240000,
+		.offset		= 0,
+		.mask_flags 	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "Kernel",
+		.size		= 0x100000,
+		.offset		= MTDPART_OFS_APPEND,
+	}, {
+		.name		= "Ramdisk",
+		.size		= 0x300000,
+		.offset		= MTDPART_OFS_APPEND,
+	}, {
+		.name		= "JFFS2",
+		.size		= 0x9A0000,
+		.offset		= MTDPART_OFS_APPEND,
+	}, {
+		.name		= "Settings",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
+	}
+};
+
+static struct physmap_flash_data amlm5900_flash_data = {
+	.width		= 2,
+	.parts		= amlm5900_mtd_partitions,
+	.nr_parts	= ARRAY_SIZE(amlm5900_mtd_partitions),
+};
+
+static struct platform_device amlm5900_device_nor = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev = {
+			.platform_data = &amlm5900_flash_data,
+		},
+	.num_resources	= 1,
+	.resource	= &amlm5900_nor_resource,
+};
+#endif
+
+static struct map_desc amlm5900_iodesc[] __initdata = {
+	{
+		.virtual	= (u32)S3C24XX_VA_SPI,
+		.pfn		= __phys_to_pfn(S3C2410_PA_SPI),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg amlm5900_uartcfgs[] = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	}
+};
+
+
+static struct platform_device *amlm5900_devices[] __initdata = {
+#ifdef CONFIG_FB_S3C2410
+	&s3c_device_lcd,
+#endif
+	&s3c_device_adc,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_usb,
+ 	&s3c_device_rtc,
+	&s3c_device_usbgadget,
+        &s3c_device_sdi,
+#ifdef CONFIG_MTD_PARTITIONS
+	&amlm5900_device_nor,
+#endif
+};
+
+static struct s3c24xx_board amlm5900_board __initdata = {
+	.devices       = amlm5900_devices,
+	.devices_count = ARRAY_SIZE(amlm5900_devices)
+};
+
+void __init amlm5900_map_io(void)
+{
+	s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
+	s3c24xx_init_clocks(0);
+	s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs));
+	s3c24xx_set_board(&amlm5900_board);
+}
+
+#ifdef CONFIG_FB_S3C2410
+static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = {
+	.width		= 160,
+	.height		= 160,
+
+/* commented out until stn patch is submitted
+*	.type		= S3C2410_LCDCON1_STN4,
+*/
+	.gpccon =	0xaaaaaaaa,
+	.gpccon_mask =	0xffffffff,
+	.gpcup =	0x0000ffff,
+	.gpcup_mask =	0xffffffff,
+
+	.gpdcon =	0xaaaaaaaa,
+	.gpdcon_mask =	0xffffffff,
+	.gpdup =	0x0000ffff,
+	.gpdup_mask =	0xffffffff,
+
+	.xres		= {
+		.min		= 160,
+		.max		= 160,
+		.defval		= 160,
+	},
+
+	.yres		= {
+		.min		= 160,
+		.max	        = 160,
+		.defval		= 160,
+	},
+
+	.bpp		= {
+		.min		= 4,
+		.max		= 4,
+		.defval		= 4,
+	},
+
+	.regs		= {
+		.lcdcon1	= 0x00008225,
+		.lcdcon2	= 0x0027c000,
+		.lcdcon3	= 0x00182708,
+		.lcdcon4	= 0x00000002,
+		.lcdcon5	= 0x00000001,
+	}
+};
+#endif
+
+static irqreturn_t
+amlm5900_wake_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+	return IRQ_HANDLED;
+}
+
+static void amlm5900_init_pm(void)
+{
+	int ret = 0;
+
+	ret = request_irq(IRQ_EINT9, &amlm5900_wake_interrupt,
+				IRQF_TRIGGER_RISING | IRQF_SHARED,
+				"amlm5900_wakeup", &amlm5900_wake_interrupt);
+	if (ret != 0) {
+		printk(KERN_ERR "AML-M5900: no wakeup irq, %d?\n", ret);
+	} else {
+		enable_irq_wake(IRQ_EINT9);
+		/* configure the suspend/resume status pin */
+		s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP);
+		s3c2410_gpio_pullup(S3C2410_GPF2, 0);
+	}
+}
+static void __init amlm5900_init(void)
+{
+	amlm5900_init_pm();
+#ifdef CONFIG_FB_S3C2410
+	s3c24xx_fb_set_platdata(&amlm5900_lcd_info);
+#endif
+}
+
+MACHINE_START(AML_M5900, "AML_M5900")
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= amlm5900_map_io,
+	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= amlm5900_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 60641d4..e94cdcd 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -4,15 +4,9 @@
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
  *
- *
- *
  * 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.
- *
- * Modifications:
- *	02-May-2005 BJD  Copied from mach-bast.c
- *	20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index d661c6b..e2205ff 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -11,15 +11,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Modifications:
- *	01-Nov-2004 BJD   Initial version
- *	12-Nov-2004 BJD   Updated for release
- *	04-Jan-2005 BJD   Fixes for pre-release
- *	22-Feb-2005 BJD   Updated for 2.6.11-rc5 relesa
- *	10-Mar-2005 LCVR  Replaced S3C2410_VA by S3C24XX_VA
- *	14-Mar-2005 BJD	  void __iomem fixes
- *	20-Sep-2005 BJD   Added static to non-exported items
- *	26-Oct-2005 BJD   Added framebuffer data
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/mach-vstms.c b/arch/arm/mach-s3c2410/mach-vstms.c
new file mode 100644
index 0000000..ea554e7
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-vstms.c
@@ -0,0 +1,168 @@
+/* linux/arch/arm/mach-s3c2410/mach-vstms.c
+ *
+ * (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Derived from mach-smdk2413.c - (C) 2006 Simtec Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include <asm/arch/nand.h>
+
+#include "s3c2410.h"
+#include "s3c2412.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+
+static struct map_desc vstms_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg vstms_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	}
+};
+
+static struct mtd_partition vstms_nand_part[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= 0x7C000,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "UBoot Config",
+		.offset = 0x7C000,
+		.size	= 0x4000,
+	},
+	[2] = {
+		.name	= "Kernel",
+		.offset = 0x80000,
+		.size	= 0x200000,
+	},
+	[3] = {
+		.name	= "RFS",
+		.offset	= 0x280000,
+		.size	= 0x3d80000,
+	},
+};
+
+static struct s3c2410_nand_set vstms_nand_sets[] = {
+	[0] = {
+		.name		= "NAND",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(vstms_nand_part),
+		.partitions	= vstms_nand_part,
+	},
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand vstms_nand_info = {
+	.tacls		= 20,
+	.twrph0		= 60,
+	.twrph1		= 20,
+	.nr_sets	= ARRAY_SIZE(vstms_nand_sets),
+	.sets		= vstms_nand_sets,
+};
+
+static struct platform_device *vstms_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+	&s3c_device_rtc,
+	&s3c_device_nand,
+};
+
+static struct s3c24xx_board vstms_board __initdata = {
+	.devices       = vstms_devices,
+	.devices_count = ARRAY_SIZE(vstms_devices)
+};
+
+static void __init vstms_fixup(struct machine_desc *desc,
+				  struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
+{
+	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+		mi->nr_banks=1;
+		mi->bank[0].start = 0x30000000;
+		mi->bank[0].size = SZ_64M;
+		mi->bank[0].node = 0;
+	}
+}
+
+static void __init vstms_map_io(void)
+{
+	s3c_device_nand.dev.platform_data = &vstms_nand_info;
+
+	s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
+	s3c24xx_set_board(&vstms_board);
+}
+
+MACHINE_START(VSTMS, "VSTMS")
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= vstms_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= vstms_map_io,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
index 7b24456..42cd05e2 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/mach-s3c2410/pm-simtec.c
@@ -49,7 +49,8 @@
 	/* check which machine we are running on */
 
 	if (!machine_is_bast() && !machine_is_vr1000() &&
-	    !machine_is_anubis() && !machine_is_osiris())
+	    !machine_is_anubis() && !machine_is_osiris() &&
+	    !machine_is_aml_m5900())
 		return 0;
 
 	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index a589fe7..b49a0b3 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/pm.c
  *
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2004,2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 Power Manager (Suspend-To-RAM) support
+ * S3C24XX Power Manager (Suspend-To-RAM) support
  *
  * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
  *
@@ -24,9 +24,6 @@
  * Parts based on arch/arm/mach-pxa/pm.c
  *
  * Thanks to Dimitry Andric for debugging
- *
- * Modifications:
- *     10-Mar-2005 LCVR  Changed S3C2410_VA_UART to S3C24XX_VA_UART
 */
 
 #include <linux/init.h>
@@ -38,6 +35,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 
+#include <asm/cacheflush.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 
@@ -55,14 +53,6 @@
 
 unsigned long s3c_pm_flags;
 
-/* cache functions from arch/arm/mm/proc-arm920.S */
-
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-extern void arm920_flush_kern_cache_all(void);
-#else
-static void arm920_flush_kern_cache_all(void) { }
-#endif
-
 #define PFX "s3c24xx-pm: "
 
 static struct sleep_save core_save[] = {
@@ -92,19 +82,6 @@
 	SAVE_ITEM(S3C2410_REFRESH),
 };
 
-/* this lot should be really saved by the IRQ code */
-static struct sleep_save irq_save[] = {
-	SAVE_ITEM(S3C2410_EXTINT0),
-	SAVE_ITEM(S3C2410_EXTINT1),
-	SAVE_ITEM(S3C2410_EXTINT2),
-	SAVE_ITEM(S3C2410_EINFLT0),
-	SAVE_ITEM(S3C2410_EINFLT1),
-	SAVE_ITEM(S3C2410_EINFLT2),
-	SAVE_ITEM(S3C2410_EINFLT3),
-	SAVE_ITEM(S3C2410_EINTMASK),
-	SAVE_ITEM(S3C2410_INTMSK)
-};
-
 static struct sleep_save gpio_save[] = {
 	SAVE_ITEM(S3C2410_GPACON),
 	SAVE_ITEM(S3C2410_GPADAT),
@@ -165,7 +142,7 @@
 
 extern void printascii(const char *);
 
-static void pm_dbg(const char *fmt, ...)
+void pm_dbg(const char *fmt, ...)
 {
 	va_list va;
 	char buff[256];
@@ -509,6 +486,9 @@
 	}
 }
 
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
 #define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
 
 /* s3c2410_pm_enter
@@ -519,7 +499,6 @@
 static int s3c2410_pm_enter(suspend_state_t state)
 {
 	unsigned long regs_save[16];
-	unsigned long tmp;
 
 	/* ensure the debug is initialised (if enabled) */
 
@@ -527,6 +506,11 @@
 
 	DBG("s3c2410_pm_enter(%d)\n", state);
 
+	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+		printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
+		return -EINVAL;
+	}
+
 	if (state != PM_SUSPEND_MEM) {
 		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
 		return -EINVAL;
@@ -554,17 +538,9 @@
 
 	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
 
-	/* ensure at least GESTATUS3 has the resume address */
-
-	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
-
-	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
-	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
-
 	/* save all necessary core registers not covered by the drivers */
 
 	s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
-	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
 	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
 	s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
 
@@ -581,10 +557,16 @@
 	/* ack any outstanding external interrupts before we go to sleep */
 
 	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+	/* call cpu specific preperation */
+
+	pm_cpu_prep();
 
 	/* flush cache back to ram */
 
-	arm920_flush_kern_cache_all();
+	flush_cache_all();
 
 	s3c2410_pm_check_store();
 
@@ -592,23 +574,23 @@
 
 	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
 
-	s3c2410_cpu_suspend(regs_save);
+	/* s3c2410_cpu_save will also act as our return point from when
+	 * we resume as it saves its own register state, so use the return
+	 * code to differentiate return from save and return from sleep */
+
+	if (s3c2410_cpu_save(regs_save) == 0) {
+		flush_cache_all();
+		pm_cpu_sleep();
+	}
 
 	/* restore the cpu state */
 
 	cpu_init();
 
-	/* unset the return-from-sleep flag, to ensure reset */
-
-	tmp = __raw_readl(S3C2410_GSTATUS2);
-	tmp &= S3C2410_GSTATUS2_OFFRESET;
-	__raw_writel(tmp, S3C2410_GSTATUS2);
-
 	/* restore the system state */
 
 	s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
 	s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
-	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
 	s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
 
 	s3c2410_pm_debug_init();
diff --git a/arch/arm/mach-s3c2410/pm.h b/arch/arm/mach-s3c2410/pm.h
index 7a5e714..ffe197a 100644
--- a/arch/arm/mach-s3c2410/pm.h
+++ b/arch/arm/mach-s3c2410/pm.h
@@ -34,13 +34,19 @@
 extern unsigned long s3c_irqwake_intallow;
 extern unsigned long s3c_irqwake_eintallow;
 
+/* per-cpu sleep functions */
+
+extern void (*pm_cpu_prep)(void);
+extern void (*pm_cpu_sleep)(void);
+
 /* Flags for PM Control */
 
 extern unsigned long s3c_pm_flags;
 
 /* from sleep.S */
 
-extern void s3c2410_cpu_suspend(unsigned long *saveblk);
+extern int  s3c2410_cpu_save(unsigned long *saveblk);
+extern void s3c2410_cpu_suspend(void);
 extern void s3c2410_cpu_resume(void);
 
 extern unsigned long s3c2410_sleep_save_phys;
@@ -57,3 +63,11 @@
 
 extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
 extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
+
+#ifdef CONFIG_PM
+extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
+extern int s3c24xx_irq_resume(struct sys_device *dev);
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
new file mode 100644
index 0000000..51e5098
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2410-dma.c
@@ -0,0 +1,158 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
+ *
+ * (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include "dma.h"
+
+#include "cpu.h"
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_USB_EP1] = {
+		.name		= "usb-ep1",
+		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP2] = {
+		.name		= "usb-ep2",
+		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP3] = {
+		.name		= "usb-ep3",
+		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP4] = {
+		.name		= "usb-ep4",
+		.channels[3]	=S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+	},
+};
+
+static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
+{
+	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
+	.select		= s3c2410_dma_select,
+	.dcon_mask	= 7 << 24,
+	.map		= s3c2410_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2410_dma_mappings),
+};
+
+static int s3c2410_dma_add(struct sys_device *sysdev)
+{
+	return s3c24xx_dma_init_map(&s3c2410_dma_sel);
+}
+
+static struct sysdev_driver s3c2410_dma_driver = {
+	.add	= s3c2410_dma_add,
+};
+
+static int __init s3c2410_dma_init(void)
+{
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
+}
+
+arch_initcall(s3c2410_dma_init);
+
+/* S3C2442 DMA contains the same selection table as the S3C2410 */
+
+static struct sysdev_driver s3c2442_dma_driver = {
+	.add	= s3c2410_dma_add,
+};
+
+static int __init s3c2442_dma_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
+}
+
+arch_initcall(s3c2442_dma_init);
+
+
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c
new file mode 100644
index 0000000..c796c9c
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2410-irq.c
@@ -0,0 +1,48 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-irq.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include "cpu.h"
+#include "pm.h"
+
+static int s3c2410_irq_add(struct sys_device *sysdev)
+{
+	return 0;
+}
+
+static struct sysdev_driver s3c2410_irq_driver = {
+	.add		= s3c2410_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
+};
+
+static int s3c2410_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
+}
+
+arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
new file mode 100644
index 0000000..e51d766
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2410-pm.c
@@ -0,0 +1,120 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-pm.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
+ *
+ * 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/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "pm.h"
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+extern void pm_dbg(const char *fmt, ...);
+#define DBG(fmt...) pm_dbg(fmt)
+#else
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
+#endif
+
+static void s3c2410_pm_prepare(void)
+{
+	/* ensure at least GSTATUS3 has the resume address */
+
+	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
+
+	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
+
+	if ( machine_is_aml_m5900() )
+		s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+
+}
+
+int s3c2410_pm_resume(struct sys_device *dev)
+{
+	unsigned long tmp;
+
+	/* unset the return-from-sleep flag, to ensure reset */
+
+	tmp = __raw_readl(S3C2410_GSTATUS2);
+	tmp &= S3C2410_GSTATUS2_OFFRESET;
+	__raw_writel(tmp, S3C2410_GSTATUS2);
+
+	if ( machine_is_aml_m5900() )
+		s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+
+	return 0;
+}
+
+static int s3c2410_pm_add(struct sys_device *dev)
+{
+	pm_cpu_prep = s3c2410_pm_prepare;
+	pm_cpu_sleep = s3c2410_cpu_suspend;
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2410_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
+};
+
+/* register ourselves */
+
+static int __init s3c2410_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
+}
+
+arch_initcall(s3c2410_pm_drvinit);
+
+static struct sysdev_driver s3c2440_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
+};
+
+static int __init s3c2440_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
+}
+
+arch_initcall(s3c2440_pm_drvinit);
+
+static struct sysdev_driver s3c2442_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
+};
+
+static int __init s3c2442_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
+}
+
+arch_initcall(s3c2442_pm_drvinit);
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S
new file mode 100644
index 0000000..9179a10
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2410-sleep.S
@@ -0,0 +1,68 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *	Cliff Brake, (c) 2001
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-serial.h>
+
+	/* s3c2410_cpu_suspend
+	 *
+	 * put the cpu into sleep mode
+	*/
+
+ENTRY(s3c2410_cpu_suspend)
+	@@ prepare cpu to sleep
+
+	ldr	r4, =S3C2410_REFRESH
+	ldr	r5, =S3C24XX_MISCCR
+	ldr	r6, =S3C2410_CLKCON
+	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
+	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
+	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
+
+	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
+	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
+	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command
+
+	teq	pc, #0			@ first as a trial-run to load cache
+	bl	s3c2410_do_sleep
+	teq	r0, r0			@ now do it for real
+	b	s3c2410_do_sleep	@
+
+	@@ align next bit of code to cache line
+	.align	8
+s3c2410_do_sleep:
+	streq	r7, [ r4 ]			@ SDRAM sleep command
+	streq	r8, [ r5 ]			@ SDRAM power-down config
+	streq	r9, [ r6 ]			@ CPU sleep
+1:	beq	1b
+	mov	pc, r14
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index a110cff..183e403 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -8,17 +8,6 @@
  * 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.
- *
- * Modifications:
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to kernel v2.6
- *     18-Jan-2004 BJD  Added serial port configuration
- *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
- *     28-Sep-2004 BJD  Updates for new serial port bits
- *     04-Nov-2004 BJD  Updated UART configuration process
- *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
- *     13-Aug-2005 DA   Removed UART from initial I/O mappings
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2410/s3c2412-dma.c
new file mode 100644
index 0000000..171f370
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412-dma.c
@@ -0,0 +1,160 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c
+ *
+ * (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include <asm/io.h>
+
+#include "dma.h"
+#include "cpu.h"
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
+
+static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels	= MAP(S3C2412_DMAREQSEL_XDREQ0),
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels	= MAP(S3C2412_DMAREQSEL_XDREQ1),
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels	= MAP(S3C2412_DMAREQSEL_SDI),
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels	= MAP(S3C2412_DMAREQSEL_SPI0TX),
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels	= MAP(S3C2412_DMAREQSEL_SPI1TX),
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART0_0),
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART1_0),
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART2_0),
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_UART0_SRC2] = {
+		.name		= "uart0",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART0_1),
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1_SRC2] = {
+		.name		= "uart1",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART1_1),
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2_SRC2] = {
+		.name		= "uart2",
+		.channels	= MAP(S3C2412_DMAREQSEL_UART2_1),
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels	= MAP(S3C2412_DMAREQSEL_TIMER),
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels	= MAP(S3C2412_DMAREQSEL_I2SRX),
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels	= MAP(S3C2412_DMAREQSEL_I2STX),
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_USB_EP1] = {
+		.name		= "usb-ep1",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP1),
+	},
+	[DMACH_USB_EP2] = {
+		.name		= "usb-ep2",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP2),
+	},
+	[DMACH_USB_EP3] = {
+		.name		= "usb-ep3",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP3),
+	},
+	[DMACH_USB_EP4] = {
+		.name		= "usb-ep4",
+		.channels	= MAP(S3C2412_DMAREQSEL_USBEP4),
+	},
+};
+
+static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
+{
+	writel(chan->regs + S3C2412_DMA_DMAREQSEL,
+	       map->channels[0] | S3C2412_DMAREQSEL_HW);
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
+	.select		= s3c2412_dma_select,
+	.dcon_mask	= 0,
+	.map		= s3c2412_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2412_dma_mappings),
+};
+
+static int s3c2412_dma_add(struct sys_device *sysdev)
+{
+	return s3c24xx_dma_init_map(&s3c2412_dma_sel);
+}
+
+static struct sysdev_driver s3c2412_dma_driver = {
+	.add	= s3c2412_dma_add,
+};
+
+static int __init s3c2412_dma_init(void)
+{
+	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_dma_driver);
+}
+
+arch_initcall(s3c2412_dma_init);
diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2410/s3c2412-irq.c
index c80ec93..7f74154 100644
--- a/arch/arm/mach-s3c2410/s3c2412-irq.c
+++ b/arch/arm/mach-s3c2410/s3c2412-irq.c
@@ -37,6 +37,7 @@
 
 #include "cpu.h"
 #include "irq.h"
+#include "pm.h"
 
 /* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
  * having them turn up in both the INT* and the EINT* registers. Whilst
@@ -120,6 +121,8 @@
 
 static struct sysdev_driver s3c2412_irq_driver = {
 	.add		= s3c2412_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
 };
 
 static int s3c2412_irq_init(void)
diff --git a/arch/arm/mach-s3c2410/s3c2412-pm.c b/arch/arm/mach-s3c2410/s3c2412-pm.c
new file mode 100644
index 0000000..19b6332
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412-pm.c
@@ -0,0 +1,128 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "cpu.h"
+#include "pm.h"
+
+#include "s3c2412.h"
+
+static void s3c2412_cpu_suspend(void)
+{
+	unsigned long tmp;
+
+	/* set our standby method to sleep */
+
+	tmp = __raw_readl(S3C2412_PWRCFG);
+	tmp |= S3C2412_PWRCFG_STANDBYWFI_SLEEP;
+	__raw_writel(tmp, S3C2412_PWRCFG);
+
+	/* issue the standby signal into the pm unit. Note, we
+	 * issue a write-buffer drain just in case */
+
+	tmp = 0;
+
+	asm("b 1f\n\t"
+	    ".align 5\n\t"
+	    "1:\n\t"
+	    "mcr p15, 0, %0, c7, c10, 4\n\t"
+	    "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
+
+	/* we should never get past here */
+
+	panic("sleep resumed to originator?");
+}
+
+static void s3c2412_pm_prepare(void)
+{
+}
+
+static int s3c2412_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = s3c2412_pm_prepare;
+	pm_cpu_sleep = s3c2412_cpu_suspend;
+
+	return 0;
+}
+
+static struct sleep_save s3c2412_sleep[] = {
+	SAVE_ITEM(S3C2412_DSC0),
+	SAVE_ITEM(S3C2412_DSC1),
+	SAVE_ITEM(S3C2413_GPJDAT),
+	SAVE_ITEM(S3C2413_GPJCON),
+	SAVE_ITEM(S3C2413_GPJUP),
+
+	/* save the PWRCFG to get back to original sleep method */
+
+	SAVE_ITEM(S3C2412_PWRCFG),
+
+	/* save the sleep configuration anyway, just in case these
+	 * get damaged during wakeup */
+
+	SAVE_ITEM(S3C2412_GPBSLPCON),
+	SAVE_ITEM(S3C2412_GPCSLPCON),
+	SAVE_ITEM(S3C2412_GPDSLPCON),
+	SAVE_ITEM(S3C2412_GPESLPCON),
+	SAVE_ITEM(S3C2412_GPFSLPCON),
+	SAVE_ITEM(S3C2412_GPGSLPCON),
+	SAVE_ITEM(S3C2412_GPHSLPCON),
+	SAVE_ITEM(S3C2413_GPJSLPCON),
+};
+
+static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+static int s3c2412_pm_resume(struct sys_device *dev)
+{
+	unsigned long tmp;
+
+	tmp = __raw_readl(S3C2412_PWRCFG);
+	tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
+	tmp |=  S3C2412_PWRCFG_STANDBYWFI_IDLE;
+	__raw_writel(tmp, S3C2412_PWRCFG);
+
+	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+static struct sysdev_driver s3c2412_pm_driver = {
+	.add		= s3c2412_pm_add,
+	.suspend	= s3c2412_pm_suspend,
+	.resume		= s3c2412_pm_resume,
+};
+
+static __init int s3c2412_pm_init(void)
+{
+	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
+}
+
+arch_initcall(s3c2412_pm_init);
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c
index 2d163f7..e76431c 100644
--- a/arch/arm/mach-s3c2410/s3c2412.c
+++ b/arch/arm/mach-s3c2410/s3c2412.c
@@ -8,17 +8,6 @@
  * 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.
- *
- * Modifications:
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to kernel v2.6
- *     18-Jan-2004 BJD  Added serial port configuration
- *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
- *     28-Sep-2004 BJD  Updates for new serial port bits
- *     04-Nov-2004 BJD  Updated UART configuration process
- *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
- *     13-Aug-2005 DA   Removed UART from initial I/O mappings
 */
 
 #include <linux/kernel.h>
@@ -56,6 +45,13 @@
 
 #ifndef CONFIG_CPU_S3C2412_ONLY
 void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
+
+static inline void s3c2412_init_gpio2(void)
+{
+	s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+}
+#else
+#define s3c2412_init_gpio2() do { } while(0)
 #endif
 
 /* Initial IO mappings */
@@ -76,6 +72,7 @@
 
 	/* rename devices that are s3c2412/s3c2413 specific */
 	s3c_device_sdi.name  = "s3c2412-sdi";
+	s3c_device_lcd.name  = "s3c2412-lcd";
 	s3c_device_nand.name = "s3c2412-nand";
 }
 
@@ -110,7 +107,7 @@
 {
 	/* move base of IO */
 
-	s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+	s3c2412_init_gpio2();
 
 	/* set our idle function */
 
@@ -161,48 +158,8 @@
  * as a driver which may support both 2410 and 2440 may try and use it.
 */
 
-#ifdef CONFIG_PM
-static struct sleep_save s3c2412_sleep[] = {
-	SAVE_ITEM(S3C2412_DSC0),
-	SAVE_ITEM(S3C2412_DSC1),
-	SAVE_ITEM(S3C2413_GPJDAT),
-	SAVE_ITEM(S3C2413_GPJCON),
-	SAVE_ITEM(S3C2413_GPJUP),
-
-	/* save the sleep configuration anyway, just in case these
-	 * get damaged during wakeup */
-
-	SAVE_ITEM(S3C2412_GPBSLPCON),
-	SAVE_ITEM(S3C2412_GPCSLPCON),
-	SAVE_ITEM(S3C2412_GPDSLPCON),
-	SAVE_ITEM(S3C2412_GPESLPCON),
-	SAVE_ITEM(S3C2412_GPFSLPCON),
-	SAVE_ITEM(S3C2412_GPGSLPCON),
-	SAVE_ITEM(S3C2412_GPHSLPCON),
-	SAVE_ITEM(S3C2413_GPJSLPCON),
-};
-
-static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
-{
-	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
-	return 0;
-}
-
-static int s3c2412_resume(struct sys_device *dev)
-{
-	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
-	return 0;
-}
-
-#else
-#define s3c2412_suspend NULL
-#define s3c2412_resume  NULL
-#endif
-
 struct sysdev_class s3c2412_sysclass = {
 	set_kset_name("s3c2412-core"),
-	.suspend	= s3c2412_suspend,
-	.resume		= s3c2412_resume
 };
 
 static int __init s3c2412_core_init(void)
diff --git a/arch/arm/mach-s3c2410/s3c2440-dma.c b/arch/arm/mach-s3c2410/s3c2440-dma.c
new file mode 100644
index 0000000..11e109c
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2440-dma.c
@@ -0,0 +1,164 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c
+ *
+ * (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2440 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include "dma.h"
+
+#include "cpu.h"
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+		.channels[1]	= S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels[0]	= S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_PCM_IN] = {
+		.name		= "pcm-in",
+		.channels[0]	= S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
+		.channels[2]	= S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
+		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+	},
+	[DMACH_PCM_OUT] = {
+		.name		= "pcm-out",
+		.channels[1]	= S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
+		.channels[3]	= S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
+		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+	},
+	[DMACH_MIC_IN] = {
+		.name		= "mic-in",
+		.channels[2]	= S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
+		.channels[3]	= S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
+		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
+	},
+	[DMACH_USB_EP1] = {
+		.name		= "usb-ep1",
+		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP2] = {
+		.name		= "usb-ep2",
+		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP3] = {
+		.name		= "usb-ep3",
+		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP4] = {
+		.name		= "usb-ep4",
+		.channels[3]	= S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+	},
+};
+
+static void s3c2440_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
+{
+	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
+	.select		= s3c2440_dma_select,
+	.dcon_mask	= 7 << 24,
+	.map		= s3c2440_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2440_dma_mappings),
+};
+
+static int s3c2440_dma_add(struct sys_device *sysdev)
+{
+	return s3c24xx_dma_init_map(&s3c2440_dma_sel);
+}
+
+static struct sysdev_driver s3c2440_dma_driver = {
+	.add	= s3c2440_dma_add,
+};
+
+static int __init s3c2440_dma_init(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver);
+}
+
+arch_initcall(s3c2440_dma_init);
+
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c
index 16fa2a3..c92ea66 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dsc.c
+++ b/arch/arm/mach-s3c2410/s3c2440-dsc.c
@@ -8,11 +8,6 @@
  * 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.
- *
- * Modifications:
- *     29-Aug-2004 BJD  Start of drive-strength control
- *     09-Nov-2004 BJD  Added symbol export
- *     11-Jan-2005 BJD  Include fix
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c
index 1667ba1..fc08feb 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2410/s3c2440-irq.c
@@ -119,7 +119,7 @@
 }
 
 static struct sysdev_driver s3c2440_irq_driver = {
-	.add	= s3c2440_irq_add,
+	.add		= s3c2440_irq_add,
 };
 
 static int s3c2440_irq_init(void)
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
index 44c5aff..0d13546 100644
--- a/arch/arm/mach-s3c2410/s3c244x-irq.c
+++ b/arch/arm/mach-s3c2410/s3c244x-irq.c
@@ -120,7 +120,9 @@
 }
 
 static struct sysdev_driver s3c2440_irq_driver = {
-	.add	= s3c244x_irq_add,
+	.add		= s3c244x_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
 };
 
 static int s3c2440_irq_init(void)
@@ -131,9 +133,12 @@
 arch_initcall(s3c2440_irq_init);
 
 static struct sysdev_driver s3c2442_irq_driver = {
-	.add	= s3c244x_irq_add,
+	.add		= s3c244x_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
 };
 
+
 static int s3c2442_irq_init(void)
 {
 	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver);
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index a7561a7..2018c2e 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -41,15 +41,25 @@
 
 	.text
 
-	/* s3c2410_cpu_suspend
+	/* s3c2410_cpu_save
 	 *
-	 * put the cpu into sleep mode
+	 * save enough of the CPU state to allow us to re-start
+	 * pm.c code. as we store items like the sp/lr, we will
+	 * end up returning from this function when the cpu resumes
+	 * so the return value is set to mark this.
+	 *
+	 * This arangement means we avoid having to flush the cache
+	 * from this code.
 	 *
 	 * entry:
-	 *	r0 = sleep save block
+	 *	r0 = pointer to save block
+	 *
+	 * exit:
+	 *	r0 = 0 => we stored everything
+	 *	     1 => resumed from sleep
 	*/
 
-ENTRY(s3c2410_cpu_suspend)
+ENTRY(s3c2410_cpu_save)
 	stmfd	sp!, { r4 - r12, lr }
 
 	@@ store co-processor registers
@@ -62,44 +72,14 @@
 
 	stmia	r0, { r4 - r13 }
 
-	@@ flush the caches to ensure everything is back out to
-	@@ SDRAM before the core powers down
-
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	bl	arm920_flush_kern_cache_all
-#endif
-
-	@@ prepare cpu to sleep
-
-	ldr	r4, =S3C2410_REFRESH
-	ldr	r5, =S3C24XX_MISCCR
-	ldr	r6, =S3C2410_CLKCON
-	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
-	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
-	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
-
-	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
-	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
-	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command
-
-	teq	pc, #0			@ first as a trial-run to load cache
-	bl	s3c2410_do_sleep
-	teq	r0, r0			@ now do it for real
-	b	s3c2410_do_sleep	@
-
-	@@ align next bit of code to cache line
-	.align	8
-s3c2410_do_sleep:
-	streq	r7, [ r4 ]			@ SDRAM sleep command
-	streq	r8, [ r5 ]			@ SDRAM power-down config
-	streq	r9, [ r6 ]			@ CPU sleep
-1:	beq	1b
-	mov	pc, r14
+	mov	r0, #0
+	ldmfd	sp, { r4 - r12, pc }
 
 	@@ return to the caller, after having the MMU
 	@@ turned on, this restores the last bits from the
 	@@ stack
 resume_with_mmu:
+	mov	r0, #1
 	ldmfd	sp!, { r4 - r12, pc }
 
 	.ltorg
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 6b22d8f..c635efa 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -10,12 +10,6 @@
  * 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.
- *
- * Modifications:
- *	14-Sep-2004 BJD  Created
- *	18-Oct-2004 BJD  Cleanups, and added code to report OC cleared
- *	09-Aug-2005 BJD  Renamed s3c2410_report_oc to s3c2410_usb_report_oc
- *	09-Aug-2005 BJD  Ports powered only if both are enabled
 */
 
 #define DEBUG
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index a0dfa39..6496eb6 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -91,30 +91,29 @@
 /*
  * low-level UART features.
  */
-static struct locomo_dev *uart_dev = NULL;
+struct platform_device collie_locomo_device;
 
 static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl)
 {
- 	if (!uart_dev) return;
-
  	if (mctrl & TIOCM_RTS)
-		locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0);
+		locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_RTS, 0);
  	else
-		locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1);
+		locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_RTS, 1);
 
  	if (mctrl & TIOCM_DTR)
-		locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0);
+		locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_DTR, 0);
  	else
-		locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1);
+		locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_DTR, 1);
 }
 
 static u_int collie_uart_get_mctrl(struct uart_port *port)
 {
 	int ret = TIOCM_CD;
 	unsigned int r;
-	if (!uart_dev) return ret;
 
-	r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+	r = locomo_gpio_read_output(&collie_locomo_device.dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+	if (r == -ENODEV)
+		return ret;
 	if (r & LOCOMO_GPIO_CTS)
 		ret |= TIOCM_CTS;
 	if (r & LOCOMO_GPIO_DSR)
@@ -130,13 +129,11 @@
 
 static int collie_uart_probe(struct locomo_dev *dev)
 {
-	uart_dev = dev;
 	return 0;
 }
 
 static int collie_uart_remove(struct locomo_dev *dev)
 {
-	uart_dev = NULL;
 	return 0;
 }
 
@@ -170,7 +167,7 @@
 	},
 };
 
-static struct platform_device locomo_device = {
+struct platform_device collie_locomo_device = {
 	.name		= "locomo",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(locomo_resources),
@@ -178,7 +175,7 @@
 };
 
 static struct platform_device *devices[] __initdata = {
-	&locomo_device,
+	&collie_locomo_device,
 	&colliescoop_device,
 };
 
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index 41b3700..13bbd08 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -117,7 +117,6 @@
 	} else {
 		switch (size) {
 		case 1:
-			addr &= ~3;
 			v = __raw_readb(addr);
 			break;
 
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index b4f220dd..c0bfb82 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -15,6 +15,7 @@
 	select CPU_32v3
 	select CPU_CACHE_V3
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V3 if MMU
 	select CPU_TLB_V3 if MMU
 	help
@@ -24,6 +25,20 @@
 	  Say Y if you want support for the ARM610 processor.
 	  Otherwise, say N.
 
+# ARM7TDMI
+config CPU_ARM7TDMI
+	bool "Support ARM7TDMI processor"
+	depends on !MMU
+	select CPU_32v4T
+	select CPU_ABRT_LV4T
+	select CPU_CACHE_V4
+	help
+	  A 32-bit RISC microprocessor based on the ARM7 processor core
+	  which has no memory control unit and cache.
+
+	  Say Y if you want support for the ARM7TDMI processor.
+	  Otherwise, say N.
+
 # ARM710
 config CPU_ARM710
 	bool "Support ARM710 processor" if !ARCH_CLPS7500 && ARCH_RPC
@@ -31,6 +46,7 @@
 	select CPU_32v3
 	select CPU_CACHE_V3
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V3 if MMU
 	select CPU_TLB_V3 if MMU
 	help
@@ -50,6 +66,7 @@
 	select CPU_ABRT_LV4T
 	select CPU_CACHE_V4
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WT if MMU
 	select CPU_TLB_V4WT if MMU
 	help
@@ -59,6 +76,36 @@
 	  Say Y if you want support for the ARM720T processor.
 	  Otherwise, say N.
 
+# ARM740T
+config CPU_ARM740T
+	bool "Support ARM740T processor" if ARCH_INTEGRATOR
+	depends on !MMU
+	select CPU_32v4T
+	select CPU_ABRT_LV4T
+	select CPU_CACHE_V3	# although the core is v4t
+	select CPU_CP15_MPU
+	help
+	  A 32-bit RISC processor with 8KB cache or 4KB variants,
+	  write buffer and MPU(Protection Unit) built around
+	  an ARM7TDMI core.
+
+	  Say Y if you want support for the ARM740T processor.
+	  Otherwise, say N.
+
+# ARM9TDMI
+config CPU_ARM9TDMI
+	bool "Support ARM9TDMI processor"
+	depends on !MMU
+	select CPU_32v4T
+	select CPU_ABRT_NOMMU
+	select CPU_CACHE_V4
+	help
+	  A 32-bit RISC microprocessor based on the ARM9 processor core
+	  which has no memory control unit and cache.
+
+	  Say Y if you want support for the ARM9TDMI processor.
+	  Otherwise, say N.
+
 # ARM920T
 config CPU_ARM920T
 	bool "Support ARM920T processor"
@@ -68,6 +115,7 @@
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU
 	select CPU_TLB_V4WBI if MMU
 	help
@@ -89,6 +137,7 @@
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU
 	select CPU_TLB_V4WBI if MMU
 	help
@@ -108,6 +157,7 @@
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU
 	select CPU_TLB_V4WBI if MMU
  	help
@@ -126,6 +176,7 @@
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU
 	select CPU_TLB_V4WBI if MMU
 	help
@@ -136,6 +187,39 @@
 	  Say Y if you want support for the ARM926T processor.
 	  Otherwise, say N.
 
+# ARM940T
+config CPU_ARM940T
+	bool "Support ARM940T processor" if ARCH_INTEGRATOR
+	depends on !MMU
+	select CPU_32v4T
+	select CPU_ABRT_NOMMU
+	select CPU_CACHE_VIVT
+	select CPU_CP15_MPU
+	help
+	  ARM940T is a member of the ARM9TDMI family of general-
+	  purpose microprocessors with MPU and seperate 4KB
+	  instruction and 4KB data cases, each with a 4-word line
+	  length.
+
+	  Say Y if you want support for the ARM940T processor.
+	  Otherwise, say N.
+
+# ARM946E-S
+config CPU_ARM946E
+	bool "Support ARM946E-S processor" if ARCH_INTEGRATOR
+	depends on !MMU
+	select CPU_32v5
+	select CPU_ABRT_NOMMU
+	select CPU_CACHE_VIVT
+	select CPU_CP15_MPU
+	help
+	  ARM946E-S is a member of the ARM9E-S family of high-
+	  performance, 32-bit system-on-chip processor solutions.
+	  The TCM and ARMv5TE 32-bit instruction set is supported.
+
+	  Say Y if you want support for the ARM946E-S processor.
+	  Otherwise, say N.
+
 # ARM1020 - needs validating
 config CPU_ARM1020
 	bool "Support ARM1020T (rev 0) processor"
@@ -144,6 +228,7 @@
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU
 	select CPU_TLB_V4WBI if MMU
 	help
@@ -161,6 +246,7 @@
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU
 	select CPU_TLB_V4WBI if MMU
 	depends on n
@@ -172,6 +258,7 @@
 	select CPU_32v5
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU # can probably do better
 	select CPU_TLB_V4WBI if MMU
 	help
@@ -189,6 +276,7 @@
 	select CPU_32v5
 	select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU # can probably do better
 	select CPU_TLB_V4WBI if MMU
 	help
@@ -207,6 +295,7 @@
 	select CPU_ABRT_EV4
 	select CPU_CACHE_V4WB
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_COPY_V4WB if MMU
 	select CPU_TLB_V4WB if MMU
 	help
@@ -227,16 +316,18 @@
 	select CPU_ABRT_EV4
 	select CPU_CACHE_V4WB
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_TLB_V4WB if MMU
 
 # XScale
 config CPU_XSCALE
 	bool
-	depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
+	depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
 	default y
 	select CPU_32v5
 	select CPU_ABRT_EV5T
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_TLB_V4WBI if MMU
 
 # XScale Core Version 3
@@ -247,6 +338,7 @@
 	select CPU_32v5
 	select CPU_ABRT_EV5T
 	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
 	select CPU_TLB_V4WBI if MMU
 	select IO_36
 
@@ -258,6 +350,7 @@
 	select CPU_ABRT_EV6
 	select CPU_CACHE_V6
 	select CPU_CACHE_VIPT
+	select CPU_CP15_MMU
 	select CPU_COPY_V6 if MMU
 	select CPU_TLB_V6 if MMU
 
@@ -299,6 +392,9 @@
 	bool
 
 # The abort model
+config CPU_ABRT_NOMMU
+	bool
+
 config CPU_ABRT_EV4
 	bool
 
@@ -380,6 +476,23 @@
 
 endif
 
+config CPU_CP15
+	bool
+	help
+	  Processor has the CP15 register.
+
+config CPU_CP15_MMU
+	bool
+	select CPU_CP15
+	help
+	  Processor has the CP15 register, which has MMU related registers.
+
+config CPU_CP15_MPU
+	bool
+	select CPU_CP15
+	help
+	  Processor has the CP15 register, which has MPU related registers.
+
 #
 # CPU supports 36-bit I/O
 #
@@ -390,7 +503,7 @@
 
 config ARM_THUMB
 	bool "Support Thumb user binaries"
-	depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6
+	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6
 	default y
 	help
 	  Say Y if you want to include kernel support for running user space
@@ -411,23 +524,48 @@
 	  port must properly enable any big-endian related features
 	  of your chipset/board/processor.
 
+config CPU_HIGH_VECTOR
+	depends !MMU && CPU_CP15 && !CPU_ARM740T
+	bool "Select the High exception vector"
+	default n
+	help
+	  Say Y here to select high exception vector(0xFFFF0000~).
+	  The exception vector can be vary depending on the platform
+	  design in nommu mode. If your platform needs to select
+	  high exception vector, say Y.
+	  Otherwise or if you are unsure, say N, and the low exception
+	  vector (0x00000000~) will be used.
+
 config CPU_ICACHE_DISABLE
-	bool "Disable I-Cache"
-	depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6
+	bool "Disable I-Cache (I-bit)"
+	depends on CPU_CP15 && !(CPU_ARM610 || CPU_ARM710 || CPU_ARM720T || CPU_ARM740T || CPU_XSCALE || CPU_XSC3)
 	help
 	  Say Y here to disable the processor instruction cache. Unless
 	  you have a reason not to or are unsure, say N.
 
 config CPU_DCACHE_DISABLE
-	bool "Disable D-Cache"
-	depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6
+	bool "Disable D-Cache (C-bit)"
+	depends on CPU_CP15
 	help
 	  Say Y here to disable the processor data cache. Unless
 	  you have a reason not to or are unsure, say N.
 
+config CPU_DCACHE_SIZE
+	hex
+	depends on CPU_ARM740T || CPU_ARM946E
+	default 0x00001000 if CPU_ARM740T
+	default 0x00002000 # default size for ARM946E-S
+	help
+	  Some cores are synthesizable to have various sized cache. For
+	  ARM946E-S case, it can vary from 0KB to 1MB.
+	  To support such cache operations, it is efficient to know the size
+	  before compile time.
+	  If your SoC is configured to have a different size, define the value
+	  here with proper conditions.
+
 config CPU_DCACHE_WRITETHROUGH
 	bool "Force write through D-cache"
-	depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6) && !CPU_DCACHE_DISABLE
+	depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_V6) && !CPU_DCACHE_DISABLE
 	default y if CPU_ARM925T
 	help
 	  Say Y here to use the data cache in writethrough mode. Unless you
@@ -435,7 +573,7 @@
 
 config CPU_CACHE_ROUND_ROBIN
 	bool "Round robin I and D cache replacement algorithm"
-	depends on (CPU_ARM926T || CPU_ARM1020) && (!CPU_ICACHE_DISABLE || !CPU_DCACHE_DISABLE)
+	depends on (CPU_ARM926T || CPU_ARM946E || CPU_ARM1020) && (!CPU_ICACHE_DISABLE || !CPU_DCACHE_DISABLE)
 	help
 	  Say Y here to use the predictable round-robin cache replacement
 	  policy.  Unless you specifically require this or are unsure, say N.
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 21a2770..d2f5672 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -6,7 +6,7 @@
 				   iomap.o
 
 obj-$(CONFIG_MMU)		+= fault-armv.o flush.o ioremap.o mmap.o \
-				   mm-armv.o
+				   pgd.o mmu.o
 
 ifneq ($(CONFIG_MMU),y)
 obj-y				+= nommu.o
@@ -17,6 +17,7 @@
 obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
 obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
 
+obj-$(CONFIG_CPU_ABRT_NOMMU)	+= abort-nommu.o
 obj-$(CONFIG_CPU_ABRT_EV4)	+= abort-ev4.o
 obj-$(CONFIG_CPU_ABRT_EV4T)	+= abort-ev4t.o
 obj-$(CONFIG_CPU_ABRT_LV4T)	+= abort-lv4t.o
@@ -33,7 +34,7 @@
 obj-$(CONFIG_CPU_COPY_V3)	+= copypage-v3.o
 obj-$(CONFIG_CPU_COPY_V4WT)	+= copypage-v4wt.o
 obj-$(CONFIG_CPU_COPY_V4WB)	+= copypage-v4wb.o
-obj-$(CONFIG_CPU_COPY_V6)	+= copypage-v6.o mmu.o
+obj-$(CONFIG_CPU_COPY_V6)	+= copypage-v6.o context.o
 obj-$(CONFIG_CPU_SA1100)	+= copypage-v4mc.o
 obj-$(CONFIG_CPU_XSCALE)	+= copypage-xscale.o
 obj-$(CONFIG_CPU_XSC3)		+= copypage-xsc3.o
@@ -46,11 +47,16 @@
 
 obj-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o
 obj-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o
+obj-$(CONFIG_CPU_ARM7TDMI)	+= proc-arm7tdmi.o
 obj-$(CONFIG_CPU_ARM720T)	+= proc-arm720.o
+obj-$(CONFIG_CPU_ARM740T)	+= proc-arm740.o
+obj-$(CONFIG_CPU_ARM9TDMI)	+= proc-arm9tdmi.o
 obj-$(CONFIG_CPU_ARM920T)	+= proc-arm920.o
 obj-$(CONFIG_CPU_ARM922T)	+= proc-arm922.o
 obj-$(CONFIG_CPU_ARM925T)	+= proc-arm925.o
 obj-$(CONFIG_CPU_ARM926T)	+= proc-arm926.o
+obj-$(CONFIG_CPU_ARM940T)	+= proc-arm940.o
+obj-$(CONFIG_CPU_ARM946E)	+= proc-arm946.o
 obj-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o
 obj-$(CONFIG_CPU_ARM1020E)	+= proc-arm1020e.o
 obj-$(CONFIG_CPU_ARM1022)	+= proc-arm1022.o
diff --git a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S
index db743e5..9fb7b0e 100644
--- a/arch/arm/mm/abort-lv4t.S
+++ b/arch/arm/mm/abort-lv4t.S
@@ -19,11 +19,16 @@
  */
 ENTRY(v4t_late_abort)
 	tst	r3, #PSR_T_BIT			@ check for thumb mode
+#ifdef CONFIG_CPU_CP15_MMU
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
+	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
+#else
+	mov	r0, #0				@ clear r0, r1 (no FSR/FAR)
+	mov	r1, #0
+#endif
 	bne	.data_thumb_abort
 	ldr	r8, [r2]			@ read arm instruction
-	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
 	tst	r8, #1 << 20			@ L = 1 -> write?
 	orreq	r1, r1, #1 << 11		@ yes.
 	and	r7, r8, #15 << 24
diff --git a/arch/arm/mm/abort-nommu.S b/arch/arm/mm/abort-nommu.S
new file mode 100644
index 0000000..a7cc7f9e
--- /dev/null
+++ b/arch/arm/mm/abort-nommu.S
@@ -0,0 +1,19 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: nommu_early_abort
+ *
+ * Params  : r2 = address of aborted instruction
+ *         : r3 = saved SPSR
+ *
+ * Returns : r0 = 0 (abort address)
+ *	   : r1 = 0 (FSR)
+ *
+ * Note: There is no FSR/FAR on !CPU_CP15_MMU cores.
+ *       Just fill zero into the registers.
+ */
+	.align	5
+ENTRY(nommu_early_abort)
+	mov	r0, #0				@ clear r0, r1 (no FSR/FAR)
+	mov	r1, #0
+	mov	pc, lr
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index e0d21bb..aa109f0 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -735,7 +735,7 @@
 	/*
 	 * We got a fault - fix it up, or die.
 	 */
-	do_bad_area(current, current->mm, addr, fsr, regs);
+	do_bad_area(addr, fsr, regs);
 	return 0;
 
  swp:
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index b8ad5d5..b290806 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -29,9 +29,13 @@
  *	Clean and invalidate the entire cache.
  */
 ENTRY(v4_flush_kern_cache_all)
+#ifdef CPU_CP15
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c7, 0		@ flush ID cache
 	mov	pc, lr
+#else
+	/* FALLTHROUGH */
+#endif
 
 /*
  *	flush_user_cache_range(start, end, flags)
@@ -44,9 +48,13 @@
  *	- flags	- vma_area_struct flags describing address space
  */
 ENTRY(v4_flush_user_cache_range)
+#ifdef CPU_CP15
 	mov	ip, #0
 	mcreq	p15, 0, ip, c7, c7, 0		@ flush ID cache
 	mov	pc, lr
+#else
+	/* FALLTHROUGH */
+#endif
 
 /*
  *	coherent_kern_range(start, end)
@@ -108,8 +116,10 @@
  *	- end	 - virtual end address
  */
 ENTRY(v4_dma_flush_range)
+#ifdef CPU_CP15
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c7, 0		@ flush ID cache
+#endif
 	/* FALLTHROUGH */
 
 /*
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
new file mode 100644
index 0000000..79e8002
--- /dev/null
+++ b/arch/arm/mm/context.c
@@ -0,0 +1,45 @@
+/*
+ *  linux/arch/arm/mm/context.c
+ *
+ *  Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+unsigned int cpu_last_asid = { 1 << ASID_BITS };
+
+/*
+ * We fork()ed a process, and we need a new context for the child
+ * to run in.  We reserve version 0 for initial tasks so we will
+ * always allocate an ASID.
+ */
+void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	mm->context.id = 0;
+}
+
+void __new_context(struct mm_struct *mm)
+{
+	unsigned int asid;
+
+	asid = ++cpu_last_asid;
+	if (asid == 0)
+		asid = cpu_last_asid = 1 << ASID_BITS;
+
+	/*
+	 * If we've used up all our ASIDs, we need
+	 * to start a new version and flush the TLB.
+	 */
+	if ((asid & ~ASID_MASK) == 0)
+		flush_tlb_all();
+
+	mm->context.id = asid;
+}
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index fc69dcc..df1645e 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -20,6 +20,8 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+#include "mm.h"
+
 /*
  * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
  * specific hacks for copying pages efficiently.
@@ -27,8 +29,6 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
 				  L_PTE_CACHEABLE)
 
-#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
-
 static DEFINE_SPINLOCK(minicache_lock);
 
 /*
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 269ce69..3d0d3a9 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -17,6 +17,8 @@
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
+#include "mm.h"
+
 #if SHMLBA > 16384
 #error FIX ME
 #endif
@@ -24,8 +26,6 @@
 #define from_address	(0xffff8000)
 #define to_address	(0xffffc000)
 
-#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
-
 static DEFINE_SPINLOCK(v6_lock);
 
 /*
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 42a6ee2..84ebe0a 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -20,6 +20,8 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+#include "mm.h"
+
 /*
  * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
  * specific hacks for copying pages efficiently.
@@ -29,8 +31,6 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
 				  L_PTE_CACHEABLE)
 
-#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
-
 static DEFINE_SPINLOCK(minicache_lock);
 
 /*
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index c5e0622..5e658a8 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -131,10 +131,11 @@
 	force_sig_info(sig, &si, tsk);
 }
 
-void
-do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
-	    unsigned int fsr, struct pt_regs *regs)
+void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = tsk->active_mm;
+
 	/*
 	 * If we are in kernel mode at this point, we
 	 * have no context to handle this fault with.
@@ -170,7 +171,7 @@
 	if (fsr & (1 << 11)) /* write? */
 		mask = VM_WRITE;
 	else
-		mask = VM_READ|VM_EXEC;
+		mask = VM_READ|VM_EXEC|VM_WRITE;
 
 	fault = VM_FAULT_BADACCESS;
 	if (!(vma->vm_flags & mask))
@@ -197,7 +198,7 @@
 		return fault;
 	}
 
-	if (tsk->pid != 1)
+	if (!is_init(tsk))
 		goto out;
 
 	/*
@@ -319,7 +320,6 @@
 do_translation_fault(unsigned long addr, unsigned int fsr,
 		     struct pt_regs *regs)
 {
-	struct task_struct *tsk;
 	unsigned int index;
 	pgd_t *pgd, *pgd_k;
 	pmd_t *pmd, *pmd_k;
@@ -351,9 +351,7 @@
 	return 0;
 
 bad_area:
-	tsk = current;
-
-	do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
+	do_bad_area(addr, fsr, regs);
 	return 0;
 }
 
@@ -364,8 +362,7 @@
 static int
 do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
-	struct task_struct *tsk = current;
-	do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
+	do_bad_area(addr, fsr, regs);
 	return 0;
 }
 
diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h
index 73b59e8..49e9e38 100644
--- a/arch/arm/mm/fault.h
+++ b/arch/arm/mm/fault.h
@@ -1,6 +1,3 @@
-void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
-		 unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-
-void show_pte(struct mm_struct *mm, unsigned long addr);
+void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
 
 unsigned long search_exception_table(unsigned long addr);
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index d438ce4..454205b 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -15,12 +15,12 @@
 #include <asm/system.h>
 #include <asm/tlbflush.h>
 
+#include "mm.h"
+
 #ifdef CONFIG_CPU_CACHE_VIPT
 
 #define ALIAS_FLUSH_START	0xffff4000
 
-#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
-
 static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
 {
 	unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
@@ -107,7 +107,7 @@
 
 	/* VIPT non-aliasing cache */
 	if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask) &&
-	    vma->vm_flags | VM_EXEC) {
+	    vma->vm_flags & VM_EXEC) {
 		unsigned long addr = (unsigned long)kaddr;
 		/* only flushing the kernel mapping on non-aliasing VIPT */
 		__cpuc_coherent_kern_range(addr, addr + len);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index fe3f7f6..22217fe 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -25,10 +25,9 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+#include "mm.h"
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-extern void _stext, _text, _etext, __data_start, _end, __init_begin, __init_end;
+extern void _text, _etext, __data_start, _end, __init_begin, __init_end;
 extern unsigned long phys_initrd_start;
 extern unsigned long phys_initrd_size;
 
@@ -38,12 +37,6 @@
  */
 static struct meminfo meminfo __initdata = { 0, };
 
-/*
- * empty_zero_page is a special page that is used for
- * zero-initialized data and COW.
- */
-struct page *empty_zero_page;
-
 void show_mem(void)
 {
 	int free = 0, total = 0, reserved = 0;
@@ -83,16 +76,6 @@
 	printk("%d pages swap cached\n", cached);
 }
 
-static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
-{
-	return pmd_offset(pgd, virt);
-}
-
-static inline pmd_t *pmd_off_k(unsigned long virt)
-{
-	return pmd_off(pgd_offset_k(virt), virt);
-}
-
 #define for_each_nodebank(iter,mi,no)			\
 	for (iter = 0; iter < mi->nr_banks; iter++)	\
 		if (mi->bank[iter].node == no)
@@ -176,62 +159,20 @@
 	return initrd_node;
 }
 
-/*
- * Reserve the various regions of node 0
- */
-static __init void reserve_node_zero(pg_data_t *pgdat)
+static inline void map_memory_bank(struct membank *bank)
 {
-	unsigned long res_size = 0;
+#ifdef CONFIG_MMU
+	struct map_desc map;
 
-	/*
-	 * Register the kernel text and data with bootmem.
-	 * Note that this can only be in node 0.
-	 */
-#ifdef CONFIG_XIP_KERNEL
-	reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
-#else
-	reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+	map.pfn = __phys_to_pfn(bank->start);
+	map.virtual = __phys_to_virt(bank->start);
+	map.length = bank->size;
+	map.type = MT_MEMORY;
+
+	create_mapping(&map);
 #endif
-
-	/*
-	 * Reserve the page tables.  These are already in use,
-	 * and can only be in node 0.
-	 */
-	reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
-			     PTRS_PER_PGD * sizeof(pgd_t));
-
-	/*
-	 * Hmm... This should go elsewhere, but we really really need to
-	 * stop things allocating the low memory; ideally we need a better
-	 * implementation of GFP_DMA which does not assume that DMA-able
-	 * memory starts at zero.
-	 */
-	if (machine_is_integrator() || machine_is_cintegrator())
-		res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
-
-	/*
-	 * These should likewise go elsewhere.  They pre-reserve the
-	 * screen memory region at the start of main system memory.
-	 */
-	if (machine_is_edb7211())
-		res_size = 0x00020000;
-	if (machine_is_p720t())
-		res_size = 0x00014000;
-
-#ifdef CONFIG_SA1111
-	/*
-	 * Because of the SA1111 DMA bug, we want to preserve our
-	 * precious DMA-able memory...
-	 */
-	res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
-#endif
-	if (res_size)
-		reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size);
 }
 
-void __init build_mem_type_table(void);
-void __init create_mapping(struct map_desc *md);
-
 static unsigned long __init
 bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
 {
@@ -248,23 +189,18 @@
 	 * Calculate the pfn range, and map the memory banks for this node.
 	 */
 	for_each_nodebank(i, mi, node) {
+		struct membank *bank = &mi->bank[i];
 		unsigned long start, end;
-		struct map_desc map;
 
-		start = mi->bank[i].start >> PAGE_SHIFT;
-		end = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT;
+		start = bank->start >> PAGE_SHIFT;
+		end = (bank->start + bank->size) >> PAGE_SHIFT;
 
 		if (start_pfn > start)
 			start_pfn = start;
 		if (end_pfn < end)
 			end_pfn = end;
 
-		map.pfn = __phys_to_pfn(mi->bank[i].start);
-		map.virtual = __phys_to_virt(mi->bank[i].start);
-		map.length = mi->bank[i].size;
-		map.type = MT_MEMORY;
-
-		create_mapping(&map);
+		map_memory_bank(bank);
 	}
 
 	/*
@@ -346,9 +282,9 @@
 	return end_pfn;
 }
 
-static void __init bootmem_init(struct meminfo *mi)
+void __init bootmem_init(struct meminfo *mi)
 {
-	unsigned long addr, memend_pfn = 0;
+	unsigned long memend_pfn = 0;
 	int node, initrd_node, i;
 
 	/*
@@ -361,26 +297,6 @@
 	memcpy(&meminfo, mi, sizeof(meminfo));
 
 	/*
-	 * Clear out all the mappings below the kernel image.
-	 */
-	for (addr = 0; addr < MODULE_START; addr += PGDIR_SIZE)
-		pmd_clear(pmd_off_k(addr));
-#ifdef CONFIG_XIP_KERNEL
-	/* The XIP kernel is mapped in the module area -- skip over it */
-	addr = ((unsigned long)&_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
-#endif
-	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
-		pmd_clear(pmd_off_k(addr));
-
-	/*
-	 * Clear out all the kernel space mappings, except for the first
-	 * memory bank, up to the end of the vmalloc region.
-	 */
-	for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size);
-	     addr < VMALLOC_END; addr += PGDIR_SIZE)
-		pmd_clear(pmd_off_k(addr));
-
-	/*
 	 * Locate which node contains the ramdisk image, if any.
 	 */
 	initrd_node = check_initrd(mi);
@@ -413,114 +329,6 @@
 	max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET;
 }
 
-/*
- * Set up device the mappings.  Since we clear out the page tables for all
- * mappings above VMALLOC_END, we will remove any debug device mappings.
- * This means you have to be careful how you debug this function, or any
- * called function.  This means you can't use any function or debugging
- * method which may touch any device, otherwise the kernel _will_ crash.
- */
-static void __init devicemaps_init(struct machine_desc *mdesc)
-{
-	struct map_desc map;
-	unsigned long addr;
-	void *vectors;
-
-	/*
-	 * Allocate the vector page early.
-	 */
-	vectors = alloc_bootmem_low_pages(PAGE_SIZE);
-	BUG_ON(!vectors);
-
-	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
-		pmd_clear(pmd_off_k(addr));
-
-	/*
-	 * Map the kernel if it is XIP.
-	 * It is always first in the modulearea.
-	 */
-#ifdef CONFIG_XIP_KERNEL
-	map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & PGDIR_MASK);
-	map.virtual = MODULE_START;
-	map.length = ((unsigned long)&_etext - map.virtual + ~PGDIR_MASK) & PGDIR_MASK;
-	map.type = MT_ROM;
-	create_mapping(&map);
-#endif
-
-	/*
-	 * Map the cache flushing regions.
-	 */
-#ifdef FLUSH_BASE
-	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
-	map.virtual = FLUSH_BASE;
-	map.length = SZ_1M;
-	map.type = MT_CACHECLEAN;
-	create_mapping(&map);
-#endif
-#ifdef FLUSH_BASE_MINICACHE
-	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
-	map.virtual = FLUSH_BASE_MINICACHE;
-	map.length = SZ_1M;
-	map.type = MT_MINICLEAN;
-	create_mapping(&map);
-#endif
-
-	/*
-	 * Create a mapping for the machine vectors at the high-vectors
-	 * location (0xffff0000).  If we aren't using high-vectors, also
-	 * create a mapping at the low-vectors virtual address.
-	 */
-	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
-	map.virtual = 0xffff0000;
-	map.length = PAGE_SIZE;
-	map.type = MT_HIGH_VECTORS;
-	create_mapping(&map);
-
-	if (!vectors_high()) {
-		map.virtual = 0;
-		map.type = MT_LOW_VECTORS;
-		create_mapping(&map);
-	}
-
-	/*
-	 * Ask the machine support to map in the statically mapped devices.
-	 */
-	if (mdesc->map_io)
-		mdesc->map_io();
-
-	/*
-	 * Finally flush the caches and tlb to ensure that we're in a
-	 * consistent state wrt the writebuffer.  This also ensures that
-	 * any write-allocated cache lines in the vector page are written
-	 * back.  After this point, we can start to touch devices again.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-}
-
-/*
- * paging_init() sets up the page tables, initialises the zone memory
- * maps, and sets up the zero page, bad page and bad page tables.
- */
-void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
-{
-	void *zero_page;
-
-	build_mem_type_table();
-	bootmem_init(mi);
-	devicemaps_init(mdesc);
-
-	top_pmd = pmd_off_k(0xffff0000);
-
-	/*
-	 * allocate the zero page.  Note that we count on this going ok.
-	 */
-	zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
-	memzero(zero_page, PAGE_SIZE);
-	empty_zero_page = virt_to_page(zero_page);
-	flush_dcache_page(empty_zero_page);
-}
-
 static inline void free_area(unsigned long addr, unsigned long end, char *s)
 {
 	unsigned int size = (end - addr) >> 10;
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
deleted file mode 100644
index 38769f5..0000000
--- a/arch/arm/mm/mm-armv.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- *  linux/arch/arm/mm/mm-armv.c
- *
- *  Copyright (C) 1998-2005 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Page table sludge for ARM v3 and v4 processor architectures.
- */
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/nodemask.h>
-
-#include <asm/pgalloc.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/tlbflush.h>
-
-#include <asm/mach/map.h>
-
-#define CPOLICY_UNCACHED	0
-#define CPOLICY_BUFFERED	1
-#define CPOLICY_WRITETHROUGH	2
-#define CPOLICY_WRITEBACK	3
-#define CPOLICY_WRITEALLOC	4
-
-static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
-static unsigned int ecc_mask __initdata = 0;
-pgprot_t pgprot_kernel;
-
-EXPORT_SYMBOL(pgprot_kernel);
-
-pmd_t *top_pmd;
-
-struct cachepolicy {
-	const char	policy[16];
-	unsigned int	cr_mask;
-	unsigned int	pmd;
-	unsigned int	pte;
-};
-
-static struct cachepolicy cache_policies[] __initdata = {
-	{
-		.policy		= "uncached",
-		.cr_mask	= CR_W|CR_C,
-		.pmd		= PMD_SECT_UNCACHED,
-		.pte		= 0,
-	}, {
-		.policy		= "buffered",
-		.cr_mask	= CR_C,
-		.pmd		= PMD_SECT_BUFFERED,
-		.pte		= PTE_BUFFERABLE,
-	}, {
-		.policy		= "writethrough",
-		.cr_mask	= 0,
-		.pmd		= PMD_SECT_WT,
-		.pte		= PTE_CACHEABLE,
-	}, {
-		.policy		= "writeback",
-		.cr_mask	= 0,
-		.pmd		= PMD_SECT_WB,
-		.pte		= PTE_BUFFERABLE|PTE_CACHEABLE,
-	}, {
-		.policy		= "writealloc",
-		.cr_mask	= 0,
-		.pmd		= PMD_SECT_WBWA,
-		.pte		= PTE_BUFFERABLE|PTE_CACHEABLE,
-	}
-};
-
-/*
- * These are useful for identifing cache coherency
- * problems by allowing the cache or the cache and
- * writebuffer to be turned off.  (Note: the write
- * buffer should not be on and the cache off).
- */
-static void __init early_cachepolicy(char **p)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
-		int len = strlen(cache_policies[i].policy);
-
-		if (memcmp(*p, cache_policies[i].policy, len) == 0) {
-			cachepolicy = i;
-			cr_alignment &= ~cache_policies[i].cr_mask;
-			cr_no_alignment &= ~cache_policies[i].cr_mask;
-			*p += len;
-			break;
-		}
-	}
-	if (i == ARRAY_SIZE(cache_policies))
-		printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
-	flush_cache_all();
-	set_cr(cr_alignment);
-}
-
-static void __init early_nocache(char **__unused)
-{
-	char *p = "buffered";
-	printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p);
-	early_cachepolicy(&p);
-}
-
-static void __init early_nowrite(char **__unused)
-{
-	char *p = "uncached";
-	printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p);
-	early_cachepolicy(&p);
-}
-
-static void __init early_ecc(char **p)
-{
-	if (memcmp(*p, "on", 2) == 0) {
-		ecc_mask = PMD_PROTECTION;
-		*p += 2;
-	} else if (memcmp(*p, "off", 3) == 0) {
-		ecc_mask = 0;
-		*p += 3;
-	}
-}
-
-__early_param("nocache", early_nocache);
-__early_param("nowb", early_nowrite);
-__early_param("cachepolicy=", early_cachepolicy);
-__early_param("ecc=", early_ecc);
-
-static int __init noalign_setup(char *__unused)
-{
-	cr_alignment &= ~CR_A;
-	cr_no_alignment &= ~CR_A;
-	set_cr(cr_alignment);
-	return 1;
-}
-
-__setup("noalign", noalign_setup);
-
-#define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
-
-static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
-{
-	return pmd_offset(pgd, virt);
-}
-
-static inline pmd_t *pmd_off_k(unsigned long virt)
-{
-	return pmd_off(pgd_offset_k(virt), virt);
-}
-
-/*
- * need to get a 16k page for level 1
- */
-pgd_t *get_pgd_slow(struct mm_struct *mm)
-{
-	pgd_t *new_pgd, *init_pgd;
-	pmd_t *new_pmd, *init_pmd;
-	pte_t *new_pte, *init_pte;
-
-	new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
-	if (!new_pgd)
-		goto no_pgd;
-
-	memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
-
-	/*
-	 * Copy over the kernel and IO PGD entries
-	 */
-	init_pgd = pgd_offset_k(0);
-	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
-		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
-
-	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
-
-	if (!vectors_high()) {
-		/*
-		 * On ARM, first page must always be allocated since it
-		 * contains the machine vectors.
-		 */
-		new_pmd = pmd_alloc(mm, new_pgd, 0);
-		if (!new_pmd)
-			goto no_pmd;
-
-		new_pte = pte_alloc_map(mm, new_pmd, 0);
-		if (!new_pte)
-			goto no_pte;
-
-		init_pmd = pmd_offset(init_pgd, 0);
-		init_pte = pte_offset_map_nested(init_pmd, 0);
-		set_pte(new_pte, *init_pte);
-		pte_unmap_nested(init_pte);
-		pte_unmap(new_pte);
-	}
-
-	return new_pgd;
-
-no_pte:
-	pmd_free(new_pmd);
-no_pmd:
-	free_pages((unsigned long)new_pgd, 2);
-no_pgd:
-	return NULL;
-}
-
-void free_pgd_slow(pgd_t *pgd)
-{
-	pmd_t *pmd;
-	struct page *pte;
-
-	if (!pgd)
-		return;
-
-	/* pgd is always present and good */
-	pmd = pmd_off(pgd, 0);
-	if (pmd_none(*pmd))
-		goto free;
-	if (pmd_bad(*pmd)) {
-		pmd_ERROR(*pmd);
-		pmd_clear(pmd);
-		goto free;
-	}
-
-	pte = pmd_page(*pmd);
-	pmd_clear(pmd);
-	dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
-	pte_lock_deinit(pte);
-	pte_free(pte);
-	pmd_free(pmd);
-free:
-	free_pages((unsigned long) pgd, 2);
-}
-
-/*
- * Create a SECTION PGD between VIRT and PHYS in domain
- * DOMAIN with protection PROT.  This operates on half-
- * pgdir entry increments.
- */
-static inline void
-alloc_init_section(unsigned long virt, unsigned long phys, int prot)
-{
-	pmd_t *pmdp = pmd_off_k(virt);
-
-	if (virt & (1 << 20))
-		pmdp++;
-
-	*pmdp = __pmd(phys | prot);
-	flush_pmd_entry(pmdp);
-}
-
-/*
- * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
- */
-static inline void
-alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
-{
-	int i;
-
-	for (i = 0; i < 16; i += 1) {
-		alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
-
-		virt += (PGDIR_SIZE / 2);
-	}
-}
-
-/*
- * Add a PAGE mapping between VIRT and PHYS in domain
- * DOMAIN with protection PROT.  Note that due to the
- * way we map the PTEs, we must allocate two PTE_SIZE'd
- * blocks - one for the Linux pte table, and one for
- * the hardware pte table.
- */
-static inline void
-alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
-{
-	pmd_t *pmdp = pmd_off_k(virt);
-	pte_t *ptep;
-
-	if (pmd_none(*pmdp)) {
-		ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
-					       sizeof(pte_t));
-
-		__pmd_populate(pmdp, __pa(ptep) | prot_l1);
-	}
-	ptep = pte_offset_kernel(pmdp, virt);
-
-	set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
-}
-
-struct mem_types {
-	unsigned int	prot_pte;
-	unsigned int	prot_l1;
-	unsigned int	prot_sect;
-	unsigned int	domain;
-};
-
-static struct mem_types mem_types[] __initdata = {
-	[MT_DEVICE] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_WRITE,
-		.prot_l1   = PMD_TYPE_TABLE,
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
-				PMD_SECT_AP_WRITE,
-		.domain    = DOMAIN_IO,
-	},
-	[MT_CACHECLEAN] = {
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4,
-		.domain    = DOMAIN_KERNEL,
-	},
-	[MT_MINICLEAN] = {
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE,
-		.domain    = DOMAIN_KERNEL,
-	},
-	[MT_LOW_VECTORS] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_EXEC,
-		.prot_l1   = PMD_TYPE_TABLE,
-		.domain    = DOMAIN_USER,
-	},
-	[MT_HIGH_VECTORS] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_USER | L_PTE_EXEC,
-		.prot_l1   = PMD_TYPE_TABLE,
-		.domain    = DOMAIN_USER,
-	},
-	[MT_MEMORY] = {
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE,
-		.domain    = DOMAIN_KERNEL,
-	},
-	[MT_ROM] = {
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4,
-		.domain    = DOMAIN_KERNEL,
-	},
-	[MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_WRITE,
-		.prot_l1   = PMD_TYPE_TABLE,
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
-				PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
-				PMD_SECT_TEX(1),
-		.domain    = DOMAIN_IO,
-	},
-	[MT_NONSHARED_DEVICE] = {
-		.prot_l1   = PMD_TYPE_TABLE,
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_NONSHARED_DEV |
-				PMD_SECT_AP_WRITE,
-		.domain    = DOMAIN_IO,
-	}
-};
-
-/*
- * Adjust the PMD section entries according to the CPU in use.
- */
-void __init build_mem_type_table(void)
-{
-	struct cachepolicy *cp;
-	unsigned int cr = get_cr();
-	unsigned int user_pgprot, kern_pgprot;
-	int cpu_arch = cpu_architecture();
-	int i;
-
-#if defined(CONFIG_CPU_DCACHE_DISABLE)
-	if (cachepolicy > CPOLICY_BUFFERED)
-		cachepolicy = CPOLICY_BUFFERED;
-#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
-	if (cachepolicy > CPOLICY_WRITETHROUGH)
-		cachepolicy = CPOLICY_WRITETHROUGH;
-#endif
-	if (cpu_arch < CPU_ARCH_ARMv5) {
-		if (cachepolicy >= CPOLICY_WRITEALLOC)
-			cachepolicy = CPOLICY_WRITEBACK;
-		ecc_mask = 0;
-	}
-
-	/*
-	 * Xscale must not have PMD bit 4 set for section mappings.
-	 */
-	if (cpu_is_xscale())
-		for (i = 0; i < ARRAY_SIZE(mem_types); i++)
-			mem_types[i].prot_sect &= ~PMD_BIT4;
-
-	/*
-	 * ARMv5 and lower, excluding Xscale, bit 4 must be set for
-	 * page tables.
-	 */
-	if (cpu_arch < CPU_ARCH_ARMv6 && !cpu_is_xscale())
-		for (i = 0; i < ARRAY_SIZE(mem_types); i++)
-			if (mem_types[i].prot_l1)
-				mem_types[i].prot_l1 |= PMD_BIT4;
-
-	cp = &cache_policies[cachepolicy];
-	kern_pgprot = user_pgprot = cp->pte;
-
-	/*
-	 * Enable CPU-specific coherency if supported.
-	 * (Only available on XSC3 at the moment.)
-	 */
-	if (arch_is_coherent()) {
-		if (cpu_is_xsc3()) {
-			mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-			mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
-		}
-	}
-
-	/*
-	 * ARMv6 and above have extended page tables.
-	 */
-	if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
-		/*
-		 * bit 4 becomes XN which we must clear for the
-		 * kernel memory mapping.
-		 */
-		mem_types[MT_MEMORY].prot_sect &= ~PMD_SECT_XN;
-		mem_types[MT_ROM].prot_sect &= ~PMD_SECT_XN;
-
-		/*
-		 * Mark cache clean areas and XIP ROM read only
-		 * from SVC mode and no access from userspace.
-		 */
-		mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
-		mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
-		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
-
-		/*
-		 * Mark the device area as "shared device"
-		 */
-		mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
-		mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
-
-		/*
-		 * User pages need to be mapped with the ASID
-		 * (iow, non-global)
-		 */
-		user_pgprot |= L_PTE_ASID;
-
-#ifdef CONFIG_SMP
-		/*
-		 * Mark memory with the "shared" attribute for SMP systems
-		 */
-		user_pgprot |= L_PTE_SHARED;
-		kern_pgprot |= L_PTE_SHARED;
-		mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-#endif
-	}
-
-	for (i = 0; i < 16; i++) {
-		unsigned long v = pgprot_val(protection_map[i]);
-		v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot;
-		protection_map[i] = __pgprot(v);
-	}
-
-	mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot;
-	mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot;
-
-	if (cpu_arch >= CPU_ARCH_ARMv5) {
-#ifndef CONFIG_SMP
-		/*
-		 * Only use write-through for non-SMP systems
-		 */
-		mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
-		mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
-#endif
-	} else {
-		mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
-	}
-
-	pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
-				 L_PTE_DIRTY | L_PTE_WRITE |
-				 L_PTE_EXEC | kern_pgprot);
-
-	mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
-	mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
-	mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
-	mem_types[MT_ROM].prot_sect |= cp->pmd;
-
-	switch (cp->pmd) {
-	case PMD_SECT_WT:
-		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
-		break;
-	case PMD_SECT_WB:
-	case PMD_SECT_WBWA:
-		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
-		break;
-	}
-	printk("Memory policy: ECC %sabled, Data cache %s\n",
-		ecc_mask ? "en" : "dis", cp->policy);
-}
-
-#define vectors_base()	(vectors_high() ? 0xffff0000 : 0)
-
-/*
- * Create the page directory entries and any necessary
- * page tables for the mapping specified by `md'.  We
- * are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections and
- * supersections.
- */
-void __init create_mapping(struct map_desc *md)
-{
-	unsigned long virt, length;
-	int prot_sect, prot_l1, domain;
-	pgprot_t prot_pte;
-	unsigned long off = (u32)__pfn_to_phys(md->pfn);
-
-	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
-		printk(KERN_WARNING "BUG: not creating mapping for "
-		       "0x%08llx at 0x%08lx in user region\n",
-		       __pfn_to_phys((u64)md->pfn), md->virtual);
-		return;
-	}
-
-	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
-	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
-		printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
-		       "overlaps vmalloc space\n",
-		       __pfn_to_phys((u64)md->pfn), md->virtual);
-	}
-
-	domain	  = mem_types[md->type].domain;
-	prot_pte  = __pgprot(mem_types[md->type].prot_pte);
-	prot_l1   = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain);
-	prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
-
-	/*
-	 * Catch 36-bit addresses
-	 */
-	if(md->pfn >= 0x100000) {
-		if(domain) {
-			printk(KERN_ERR "MM: invalid domain in supersection "
-				"mapping for 0x%08llx at 0x%08lx\n",
-				__pfn_to_phys((u64)md->pfn), md->virtual);
-			return;
-		}
-		if((md->virtual | md->length | __pfn_to_phys(md->pfn))
-			& ~SUPERSECTION_MASK) {
-			printk(KERN_ERR "MM: cannot create mapping for "
-				"0x%08llx at 0x%08lx invalid alignment\n",
-				__pfn_to_phys((u64)md->pfn), md->virtual);
-			return;
-		}
-
-		/*
-		 * Shift bits [35:32] of address into bits [23:20] of PMD
-		 * (See ARMv6 spec).
-		 */
-		off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
-	}
-
-	virt   = md->virtual;
-	off   -= virt;
-	length = md->length;
-
-	if (mem_types[md->type].prot_l1 == 0 &&
-	    (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) {
-		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
-		       "be mapped using pages, ignoring.\n",
-		       __pfn_to_phys(md->pfn), md->virtual);
-		return;
-	}
-
-	while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) {
-		alloc_init_page(virt, virt + off, prot_l1, prot_pte);
-
-		virt   += PAGE_SIZE;
-		length -= PAGE_SIZE;
-	}
-
-	/* N.B.	ARMv6 supersections are only defined to work with domain 0.
-	 *	Since domain assignments can in fact be arbitrary, the
-	 *	'domain == 0' check below is required to insure that ARMv6
-	 *	supersections are only allocated for domain 0 regardless
-	 *	of the actual domain assignments in use.
-	 */
-	if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
-		&& domain == 0) {
-		/*
-		 * Align to supersection boundary if !high pages.
-		 * High pages have already been checked for proper
-		 * alignment above and they will fail the SUPSERSECTION_MASK
-		 * check because of the way the address is encoded into
-		 * offset.
-		 */
-		if (md->pfn <= 0x100000) {
-			while ((virt & ~SUPERSECTION_MASK ||
-			        (virt + off) & ~SUPERSECTION_MASK) &&
-				length >= (PGDIR_SIZE / 2)) {
-				alloc_init_section(virt, virt + off, prot_sect);
-
-				virt   += (PGDIR_SIZE / 2);
-				length -= (PGDIR_SIZE / 2);
-			}
-		}
-
-		while (length >= SUPERSECTION_SIZE) {
-			alloc_init_supersection(virt, virt + off, prot_sect);
-
-			virt   += SUPERSECTION_SIZE;
-			length -= SUPERSECTION_SIZE;
-		}
-	}
-
-	/*
-	 * A section mapping covers half a "pgdir" entry.
-	 */
-	while (length >= (PGDIR_SIZE / 2)) {
-		alloc_init_section(virt, virt + off, prot_sect);
-
-		virt   += (PGDIR_SIZE / 2);
-		length -= (PGDIR_SIZE / 2);
-	}
-
-	while (length >= PAGE_SIZE) {
-		alloc_init_page(virt, virt + off, prot_l1, prot_pte);
-
-		virt   += PAGE_SIZE;
-		length -= PAGE_SIZE;
-	}
-}
-
-/*
- * In order to soft-boot, we need to insert a 1:1 mapping in place of
- * the user-mode pages.  This will then ensure that we have predictable
- * results when turning the mmu off
- */
-void setup_mm_for_reboot(char mode)
-{
-	unsigned long base_pmdval;
-	pgd_t *pgd;
-	int i;
-
-	if (current->mm && current->mm->pgd)
-		pgd = current->mm->pgd;
-	else
-		pgd = init_mm.pgd;
-
-	base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
-	if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
-		base_pmdval |= PMD_BIT4;
-
-	for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
-		unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
-		pmd_t *pmd;
-
-		pmd = pmd_off(pgd, i << PGDIR_SHIFT);
-		pmd[0] = __pmd(pmdval);
-		pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
-		flush_pmd_entry(pmd);
-	}
-}
-
-/*
- * Create the architecture specific mappings
- */
-void __init iotable_init(struct map_desc *io_desc, int nr)
-{
-	int i;
-
-	for (i = 0; i < nr; i++)
-		create_mapping(io_desc + i);
-}
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
new file mode 100644
index 0000000..bb2bc9a
--- /dev/null
+++ b/arch/arm/mm/mm.h
@@ -0,0 +1,22 @@
+/* the upper-most page table pointer */
+extern pmd_t *top_pmd;
+
+#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
+
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+	return pmd_offset(pgd, virt);
+}
+
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+	return pmd_off(pgd_offset_k(virt), virt);
+}
+
+struct map_desc;
+struct meminfo;
+struct pglist_data;
+
+void __init create_mapping(struct map_desc *md);
+void __init bootmem_init(struct meminfo *mi);
+void reserve_node_zero(struct pglist_data *pgdat);
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 29e5480..b0b5f46 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -114,3 +114,25 @@
 	}
 }
 
+
+/*
+ * You really shouldn't be using read() or write() on /dev/mem.  This
+ * might go away in the future.
+ */
+int valid_phys_addr_range(unsigned long addr, size_t size)
+{
+	if (addr + size > __pa(high_memory))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * We don't use supersection mappings for mmap() on /dev/mem, which
+ * means that we can't map the memory area above the 4G barrier into
+ * userspace.
+ */
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+{
+	return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
+}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 0d90227..e566cbe 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1,45 +1,771 @@
 /*
  *  linux/arch/arm/mm/mmu.c
  *
- *  Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
+ *  Copyright (C) 1995-2005 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
 
-#include <asm/mmu_context.h>
-#include <asm/tlbflush.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
 
-unsigned int cpu_last_asid = { 1 << ASID_BITS };
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "mm.h"
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+extern void _stext, __data_start, _end;
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 /*
- * We fork()ed a process, and we need a new context for the child
- * to run in.  We reserve version 0 for initial tasks so we will
- * always allocate an ASID.
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
  */
-void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+struct page *empty_zero_page;
+
+/*
+ * The pmd table for the upper-most set of pages.
+ */
+pmd_t *top_pmd;
+
+#define CPOLICY_UNCACHED	0
+#define CPOLICY_BUFFERED	1
+#define CPOLICY_WRITETHROUGH	2
+#define CPOLICY_WRITEBACK	3
+#define CPOLICY_WRITEALLOC	4
+
+static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
+static unsigned int ecc_mask __initdata = 0;
+pgprot_t pgprot_kernel;
+
+EXPORT_SYMBOL(pgprot_kernel);
+
+struct cachepolicy {
+	const char	policy[16];
+	unsigned int	cr_mask;
+	unsigned int	pmd;
+	unsigned int	pte;
+};
+
+static struct cachepolicy cache_policies[] __initdata = {
+	{
+		.policy		= "uncached",
+		.cr_mask	= CR_W|CR_C,
+		.pmd		= PMD_SECT_UNCACHED,
+		.pte		= 0,
+	}, {
+		.policy		= "buffered",
+		.cr_mask	= CR_C,
+		.pmd		= PMD_SECT_BUFFERED,
+		.pte		= PTE_BUFFERABLE,
+	}, {
+		.policy		= "writethrough",
+		.cr_mask	= 0,
+		.pmd		= PMD_SECT_WT,
+		.pte		= PTE_CACHEABLE,
+	}, {
+		.policy		= "writeback",
+		.cr_mask	= 0,
+		.pmd		= PMD_SECT_WB,
+		.pte		= PTE_BUFFERABLE|PTE_CACHEABLE,
+	}, {
+		.policy		= "writealloc",
+		.cr_mask	= 0,
+		.pmd		= PMD_SECT_WBWA,
+		.pte		= PTE_BUFFERABLE|PTE_CACHEABLE,
+	}
+};
+
+/*
+ * These are useful for identifing cache coherency
+ * problems by allowing the cache or the cache and
+ * writebuffer to be turned off.  (Note: the write
+ * buffer should not be on and the cache off).
+ */
+static void __init early_cachepolicy(char **p)
 {
-	mm->context.id = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
+		int len = strlen(cache_policies[i].policy);
+
+		if (memcmp(*p, cache_policies[i].policy, len) == 0) {
+			cachepolicy = i;
+			cr_alignment &= ~cache_policies[i].cr_mask;
+			cr_no_alignment &= ~cache_policies[i].cr_mask;
+			*p += len;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(cache_policies))
+		printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
+	flush_cache_all();
+	set_cr(cr_alignment);
 }
+__early_param("cachepolicy=", early_cachepolicy);
 
-void __new_context(struct mm_struct *mm)
+static void __init early_nocache(char **__unused)
 {
-	unsigned int asid;
+	char *p = "buffered";
+	printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p);
+	early_cachepolicy(&p);
+}
+__early_param("nocache", early_nocache);
 
-	asid = ++cpu_last_asid;
-	if (asid == 0)
-		asid = cpu_last_asid = 1 << ASID_BITS;
+static void __init early_nowrite(char **__unused)
+{
+	char *p = "uncached";
+	printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p);
+	early_cachepolicy(&p);
+}
+__early_param("nowb", early_nowrite);
+
+static void __init early_ecc(char **p)
+{
+	if (memcmp(*p, "on", 2) == 0) {
+		ecc_mask = PMD_PROTECTION;
+		*p += 2;
+	} else if (memcmp(*p, "off", 3) == 0) {
+		ecc_mask = 0;
+		*p += 3;
+	}
+}
+__early_param("ecc=", early_ecc);
+
+static int __init noalign_setup(char *__unused)
+{
+	cr_alignment &= ~CR_A;
+	cr_no_alignment &= ~CR_A;
+	set_cr(cr_alignment);
+	return 1;
+}
+__setup("noalign", noalign_setup);
+
+struct mem_types {
+	unsigned int	prot_pte;
+	unsigned int	prot_l1;
+	unsigned int	prot_sect;
+	unsigned int	domain;
+};
+
+static struct mem_types mem_types[] __initdata = {
+	[MT_DEVICE] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_WRITE,
+		.prot_l1   = PMD_TYPE_TABLE,
+		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
+				PMD_SECT_AP_WRITE,
+		.domain    = DOMAIN_IO,
+	},
+	[MT_CACHECLEAN] = {
+		.prot_sect = PMD_TYPE_SECT | PMD_BIT4,
+		.domain    = DOMAIN_KERNEL,
+	},
+	[MT_MINICLEAN] = {
+		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE,
+		.domain    = DOMAIN_KERNEL,
+	},
+	[MT_LOW_VECTORS] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE,
+		.domain    = DOMAIN_USER,
+	},
+	[MT_HIGH_VECTORS] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_USER | L_PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE,
+		.domain    = DOMAIN_USER,
+	},
+	[MT_MEMORY] = {
+		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE,
+		.domain    = DOMAIN_KERNEL,
+	},
+	[MT_ROM] = {
+		.prot_sect = PMD_TYPE_SECT | PMD_BIT4,
+		.domain    = DOMAIN_KERNEL,
+	},
+	[MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+				L_PTE_WRITE,
+		.prot_l1   = PMD_TYPE_TABLE,
+		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
+				PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
+				PMD_SECT_TEX(1),
+		.domain    = DOMAIN_IO,
+	},
+	[MT_NONSHARED_DEVICE] = {
+		.prot_l1   = PMD_TYPE_TABLE,
+		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_NONSHARED_DEV |
+				PMD_SECT_AP_WRITE,
+		.domain    = DOMAIN_IO,
+	}
+};
+
+/*
+ * Adjust the PMD section entries according to the CPU in use.
+ */
+static void __init build_mem_type_table(void)
+{
+	struct cachepolicy *cp;
+	unsigned int cr = get_cr();
+	unsigned int user_pgprot, kern_pgprot;
+	int cpu_arch = cpu_architecture();
+	int i;
+
+#if defined(CONFIG_CPU_DCACHE_DISABLE)
+	if (cachepolicy > CPOLICY_BUFFERED)
+		cachepolicy = CPOLICY_BUFFERED;
+#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
+	if (cachepolicy > CPOLICY_WRITETHROUGH)
+		cachepolicy = CPOLICY_WRITETHROUGH;
+#endif
+	if (cpu_arch < CPU_ARCH_ARMv5) {
+		if (cachepolicy >= CPOLICY_WRITEALLOC)
+			cachepolicy = CPOLICY_WRITEBACK;
+		ecc_mask = 0;
+	}
 
 	/*
-	 * If we've used up all our ASIDs, we need
-	 * to start a new version and flush the TLB.
+	 * Xscale must not have PMD bit 4 set for section mappings.
 	 */
-	if ((asid & ~ASID_MASK) == 0)
-		flush_tlb_all();
+	if (cpu_is_xscale())
+		for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+			mem_types[i].prot_sect &= ~PMD_BIT4;
 
-	mm->context.id = asid;
+	/*
+	 * ARMv5 and lower, excluding Xscale, bit 4 must be set for
+	 * page tables.
+	 */
+	if (cpu_arch < CPU_ARCH_ARMv6 && !cpu_is_xscale())
+		for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+			if (mem_types[i].prot_l1)
+				mem_types[i].prot_l1 |= PMD_BIT4;
+
+	cp = &cache_policies[cachepolicy];
+	kern_pgprot = user_pgprot = cp->pte;
+
+	/*
+	 * Enable CPU-specific coherency if supported.
+	 * (Only available on XSC3 at the moment.)
+	 */
+	if (arch_is_coherent()) {
+		if (cpu_is_xsc3()) {
+			mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+			mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+		}
+	}
+
+	/*
+	 * ARMv6 and above have extended page tables.
+	 */
+	if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
+		/*
+		 * bit 4 becomes XN which we must clear for the
+		 * kernel memory mapping.
+		 */
+		mem_types[MT_MEMORY].prot_sect &= ~PMD_SECT_XN;
+		mem_types[MT_ROM].prot_sect &= ~PMD_SECT_XN;
+
+		/*
+		 * Mark cache clean areas and XIP ROM read only
+		 * from SVC mode and no access from userspace.
+		 */
+		mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+		mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+
+		/*
+		 * Mark the device area as "shared device"
+		 */
+		mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
+		mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
+
+		/*
+		 * User pages need to be mapped with the ASID
+		 * (iow, non-global)
+		 */
+		user_pgprot |= L_PTE_ASID;
+
+#ifdef CONFIG_SMP
+		/*
+		 * Mark memory with the "shared" attribute for SMP systems
+		 */
+		user_pgprot |= L_PTE_SHARED;
+		kern_pgprot |= L_PTE_SHARED;
+		mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+#endif
+	}
+
+	for (i = 0; i < 16; i++) {
+		unsigned long v = pgprot_val(protection_map[i]);
+		v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot;
+		protection_map[i] = __pgprot(v);
+	}
+
+	mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot;
+	mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot;
+
+	if (cpu_arch >= CPU_ARCH_ARMv5) {
+#ifndef CONFIG_SMP
+		/*
+		 * Only use write-through for non-SMP systems
+		 */
+		mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
+		mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
+#endif
+	} else {
+		mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
+	}
+
+	pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
+				 L_PTE_DIRTY | L_PTE_WRITE |
+				 L_PTE_EXEC | kern_pgprot);
+
+	mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
+	mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
+	mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
+	mem_types[MT_ROM].prot_sect |= cp->pmd;
+
+	switch (cp->pmd) {
+	case PMD_SECT_WT:
+		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
+		break;
+	case PMD_SECT_WB:
+	case PMD_SECT_WBWA:
+		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
+		break;
+	}
+	printk("Memory policy: ECC %sabled, Data cache %s\n",
+		ecc_mask ? "en" : "dis", cp->policy);
+}
+
+#define vectors_base()	(vectors_high() ? 0xffff0000 : 0)
+
+/*
+ * Create a SECTION PGD between VIRT and PHYS in domain
+ * DOMAIN with protection PROT.  This operates on half-
+ * pgdir entry increments.
+ */
+static inline void
+alloc_init_section(unsigned long virt, unsigned long phys, int prot)
+{
+	pmd_t *pmdp = pmd_off_k(virt);
+
+	if (virt & (1 << 20))
+		pmdp++;
+
+	*pmdp = __pmd(phys | prot);
+	flush_pmd_entry(pmdp);
+}
+
+/*
+ * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
+ */
+static inline void
+alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
+{
+	int i;
+
+	for (i = 0; i < 16; i += 1) {
+		alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
+
+		virt += (PGDIR_SIZE / 2);
+	}
+}
+
+/*
+ * Add a PAGE mapping between VIRT and PHYS in domain
+ * DOMAIN with protection PROT.  Note that due to the
+ * way we map the PTEs, we must allocate two PTE_SIZE'd
+ * blocks - one for the Linux pte table, and one for
+ * the hardware pte table.
+ */
+static inline void
+alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
+{
+	pmd_t *pmdp = pmd_off_k(virt);
+	pte_t *ptep;
+
+	if (pmd_none(*pmdp)) {
+		ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
+					       sizeof(pte_t));
+
+		__pmd_populate(pmdp, __pa(ptep) | prot_l1);
+	}
+	ptep = pte_offset_kernel(pmdp, virt);
+
+	set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
+}
+
+/*
+ * Create the page directory entries and any necessary
+ * page tables for the mapping specified by `md'.  We
+ * are able to cope here with varying sizes and address
+ * offsets, and we take full advantage of sections and
+ * supersections.
+ */
+void __init create_mapping(struct map_desc *md)
+{
+	unsigned long virt, length;
+	int prot_sect, prot_l1, domain;
+	pgprot_t prot_pte;
+	unsigned long off = (u32)__pfn_to_phys(md->pfn);
+
+	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
+		printk(KERN_WARNING "BUG: not creating mapping for "
+		       "0x%08llx at 0x%08lx in user region\n",
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
+		return;
+	}
+
+	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
+		printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
+		       "overlaps vmalloc space\n",
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
+	}
+
+	domain	  = mem_types[md->type].domain;
+	prot_pte  = __pgprot(mem_types[md->type].prot_pte);
+	prot_l1   = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain);
+	prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
+
+	/*
+	 * Catch 36-bit addresses
+	 */
+	if(md->pfn >= 0x100000) {
+		if(domain) {
+			printk(KERN_ERR "MM: invalid domain in supersection "
+				"mapping for 0x%08llx at 0x%08lx\n",
+				__pfn_to_phys((u64)md->pfn), md->virtual);
+			return;
+		}
+		if((md->virtual | md->length | __pfn_to_phys(md->pfn))
+			& ~SUPERSECTION_MASK) {
+			printk(KERN_ERR "MM: cannot create mapping for "
+				"0x%08llx at 0x%08lx invalid alignment\n",
+				__pfn_to_phys((u64)md->pfn), md->virtual);
+			return;
+		}
+
+		/*
+		 * Shift bits [35:32] of address into bits [23:20] of PMD
+		 * (See ARMv6 spec).
+		 */
+		off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
+	}
+
+	virt   = md->virtual;
+	off   -= virt;
+	length = md->length;
+
+	if (mem_types[md->type].prot_l1 == 0 &&
+	    (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) {
+		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
+		       "be mapped using pages, ignoring.\n",
+		       __pfn_to_phys(md->pfn), md->virtual);
+		return;
+	}
+
+	while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) {
+		alloc_init_page(virt, virt + off, prot_l1, prot_pte);
+
+		virt   += PAGE_SIZE;
+		length -= PAGE_SIZE;
+	}
+
+	/* N.B.	ARMv6 supersections are only defined to work with domain 0.
+	 *	Since domain assignments can in fact be arbitrary, the
+	 *	'domain == 0' check below is required to insure that ARMv6
+	 *	supersections are only allocated for domain 0 regardless
+	 *	of the actual domain assignments in use.
+	 */
+	if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
+		&& domain == 0) {
+		/*
+		 * Align to supersection boundary if !high pages.
+		 * High pages have already been checked for proper
+		 * alignment above and they will fail the SUPSERSECTION_MASK
+		 * check because of the way the address is encoded into
+		 * offset.
+		 */
+		if (md->pfn <= 0x100000) {
+			while ((virt & ~SUPERSECTION_MASK ||
+			        (virt + off) & ~SUPERSECTION_MASK) &&
+				length >= (PGDIR_SIZE / 2)) {
+				alloc_init_section(virt, virt + off, prot_sect);
+
+				virt   += (PGDIR_SIZE / 2);
+				length -= (PGDIR_SIZE / 2);
+			}
+		}
+
+		while (length >= SUPERSECTION_SIZE) {
+			alloc_init_supersection(virt, virt + off, prot_sect);
+
+			virt   += SUPERSECTION_SIZE;
+			length -= SUPERSECTION_SIZE;
+		}
+	}
+
+	/*
+	 * A section mapping covers half a "pgdir" entry.
+	 */
+	while (length >= (PGDIR_SIZE / 2)) {
+		alloc_init_section(virt, virt + off, prot_sect);
+
+		virt   += (PGDIR_SIZE / 2);
+		length -= (PGDIR_SIZE / 2);
+	}
+
+	while (length >= PAGE_SIZE) {
+		alloc_init_page(virt, virt + off, prot_l1, prot_pte);
+
+		virt   += PAGE_SIZE;
+		length -= PAGE_SIZE;
+	}
+}
+
+/*
+ * Create the architecture specific mappings
+ */
+void __init iotable_init(struct map_desc *io_desc, int nr)
+{
+	int i;
+
+	for (i = 0; i < nr; i++)
+		create_mapping(io_desc + i);
+}
+
+static inline void prepare_page_table(struct meminfo *mi)
+{
+	unsigned long addr;
+
+	/*
+	 * Clear out all the mappings below the kernel image.
+	 */
+	for (addr = 0; addr < MODULE_START; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+#ifdef CONFIG_XIP_KERNEL
+	/* The XIP kernel is mapped in the module area -- skip over it */
+	addr = ((unsigned long)&_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
+#endif
+	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Clear out all the kernel space mappings, except for the first
+	 * memory bank, up to the end of the vmalloc region.
+	 */
+	for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size);
+	     addr < VMALLOC_END; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+}
+
+/*
+ * Reserve the various regions of node 0
+ */
+void __init reserve_node_zero(pg_data_t *pgdat)
+{
+	unsigned long res_size = 0;
+
+	/*
+	 * Register the kernel text and data with bootmem.
+	 * Note that this can only be in node 0.
+	 */
+#ifdef CONFIG_XIP_KERNEL
+	reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
+#else
+	reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+#endif
+
+	/*
+	 * Reserve the page tables.  These are already in use,
+	 * and can only be in node 0.
+	 */
+	reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
+			     PTRS_PER_PGD * sizeof(pgd_t));
+
+	/*
+	 * Hmm... This should go elsewhere, but we really really need to
+	 * stop things allocating the low memory; ideally we need a better
+	 * implementation of GFP_DMA which does not assume that DMA-able
+	 * memory starts at zero.
+	 */
+	if (machine_is_integrator() || machine_is_cintegrator())
+		res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+
+	/*
+	 * These should likewise go elsewhere.  They pre-reserve the
+	 * screen memory region at the start of main system memory.
+	 */
+	if (machine_is_edb7211())
+		res_size = 0x00020000;
+	if (machine_is_p720t())
+		res_size = 0x00014000;
+
+#ifdef CONFIG_SA1111
+	/*
+	 * Because of the SA1111 DMA bug, we want to preserve our
+	 * precious DMA-able memory...
+	 */
+	res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+#endif
+	if (res_size)
+		reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size);
+}
+
+/*
+ * Set up device the mappings.  Since we clear out the page tables for all
+ * mappings above VMALLOC_END, we will remove any debug device mappings.
+ * This means you have to be careful how you debug this function, or any
+ * called function.  This means you can't use any function or debugging
+ * method which may touch any device, otherwise the kernel _will_ crash.
+ */
+static void __init devicemaps_init(struct machine_desc *mdesc)
+{
+	struct map_desc map;
+	unsigned long addr;
+	void *vectors;
+
+	/*
+	 * Allocate the vector page early.
+	 */
+	vectors = alloc_bootmem_low_pages(PAGE_SIZE);
+	BUG_ON(!vectors);
+
+	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Map the kernel if it is XIP.
+	 * It is always first in the modulearea.
+	 */
+#ifdef CONFIG_XIP_KERNEL
+	map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
+	map.virtual = MODULE_START;
+	map.length = ((unsigned long)&_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK;
+	map.type = MT_ROM;
+	create_mapping(&map);
+#endif
+
+	/*
+	 * Map the cache flushing regions.
+	 */
+#ifdef FLUSH_BASE
+	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
+	map.virtual = FLUSH_BASE;
+	map.length = SZ_1M;
+	map.type = MT_CACHECLEAN;
+	create_mapping(&map);
+#endif
+#ifdef FLUSH_BASE_MINICACHE
+	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
+	map.virtual = FLUSH_BASE_MINICACHE;
+	map.length = SZ_1M;
+	map.type = MT_MINICLEAN;
+	create_mapping(&map);
+#endif
+
+	/*
+	 * Create a mapping for the machine vectors at the high-vectors
+	 * location (0xffff0000).  If we aren't using high-vectors, also
+	 * create a mapping at the low-vectors virtual address.
+	 */
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.virtual = 0xffff0000;
+	map.length = PAGE_SIZE;
+	map.type = MT_HIGH_VECTORS;
+	create_mapping(&map);
+
+	if (!vectors_high()) {
+		map.virtual = 0;
+		map.type = MT_LOW_VECTORS;
+		create_mapping(&map);
+	}
+
+	/*
+	 * Ask the machine support to map in the statically mapped devices.
+	 */
+	if (mdesc->map_io)
+		mdesc->map_io();
+
+	/*
+	 * Finally flush the caches and tlb to ensure that we're in a
+	 * consistent state wrt the writebuffer.  This also ensures that
+	 * any write-allocated cache lines in the vector page are written
+	 * back.  After this point, we can start to touch devices again.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps, and sets up the zero page, bad page and bad page tables.
+ */
+void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
+{
+	void *zero_page;
+
+	build_mem_type_table();
+	prepare_page_table(mi);
+	bootmem_init(mi);
+	devicemaps_init(mdesc);
+
+	top_pmd = pmd_off_k(0xffff0000);
+
+	/*
+	 * allocate the zero page.  Note that we count on this going ok.
+	 */
+	zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
+	memzero(zero_page, PAGE_SIZE);
+	empty_zero_page = virt_to_page(zero_page);
+	flush_dcache_page(empty_zero_page);
+}
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+	unsigned long base_pmdval;
+	pgd_t *pgd;
+	int i;
+
+	if (current->mm && current->mm->pgd)
+		pgd = current->mm->pgd;
+	else
+		pgd = init_mm.pgd;
+
+	base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
+	if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+		base_pmdval |= PMD_BIT4;
+
+	for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
+		unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
+		pmd_t *pmd;
+
+		pmd = pmd_off(pgd, i << PGDIR_SHIFT);
+		pmd[0] = __pmd(pmdval);
+		pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
+		flush_pmd_entry(pmd);
+	}
 }
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 1464ed8..d0e6642 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -11,6 +11,49 @@
 #include <asm/io.h>
 #include <asm/page.h>
 
+#include "mm.h"
+
+extern void _stext, __data_start, _end;
+
+/*
+ * Reserve the various regions of node 0
+ */
+void __init reserve_node_zero(pg_data_t *pgdat)
+{
+	/*
+	 * Register the kernel text and data with bootmem.
+	 * Note that this can only be in node 0.
+	 */
+#ifdef CONFIG_XIP_KERNEL
+	reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
+#else
+	reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+#endif
+
+	/*
+	 * Register the exception vector page.
+	 * some architectures which the DRAM is the exception vector to trap,
+	 * alloc_page breaks with error, although it is not NULL, but "0."
+	 */
+	reserve_bootmem_node(pgdat, CONFIG_VECTORS_BASE, PAGE_SIZE);
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps, and sets up the zero page, bad page and bad page tables.
+ */
+void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
+{
+	bootmem_init(mi);
+}
+
+/*
+ * We don't need to do anything here for nommu machines.
+ */
+void setup_mm_for_reboot(char mode)
+{
+}
+
 void flush_dcache_page(struct page *page)
 {
 	__cpuc_flush_dcache_page(page_address(page));
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
new file mode 100644
index 0000000..20c1b0d
--- /dev/null
+++ b/arch/arm/mm/pgd.c
@@ -0,0 +1,101 @@
+/*
+ *  linux/arch/arm/mm/pgd.c
+ *
+ *  Copyright (C) 1998-2005 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/mm.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+
+#include "mm.h"
+
+#define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
+
+/*
+ * need to get a 16k page for level 1
+ */
+pgd_t *get_pgd_slow(struct mm_struct *mm)
+{
+	pgd_t *new_pgd, *init_pgd;
+	pmd_t *new_pmd, *init_pmd;
+	pte_t *new_pte, *init_pte;
+
+	new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
+	if (!new_pgd)
+		goto no_pgd;
+
+	memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
+
+	/*
+	 * Copy over the kernel and IO PGD entries
+	 */
+	init_pgd = pgd_offset_k(0);
+	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
+		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+
+	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+
+	if (!vectors_high()) {
+		/*
+		 * On ARM, first page must always be allocated since it
+		 * contains the machine vectors.
+		 */
+		new_pmd = pmd_alloc(mm, new_pgd, 0);
+		if (!new_pmd)
+			goto no_pmd;
+
+		new_pte = pte_alloc_map(mm, new_pmd, 0);
+		if (!new_pte)
+			goto no_pte;
+
+		init_pmd = pmd_offset(init_pgd, 0);
+		init_pte = pte_offset_map_nested(init_pmd, 0);
+		set_pte(new_pte, *init_pte);
+		pte_unmap_nested(init_pte);
+		pte_unmap(new_pte);
+	}
+
+	return new_pgd;
+
+no_pte:
+	pmd_free(new_pmd);
+no_pmd:
+	free_pages((unsigned long)new_pgd, 2);
+no_pgd:
+	return NULL;
+}
+
+void free_pgd_slow(pgd_t *pgd)
+{
+	pmd_t *pmd;
+	struct page *pte;
+
+	if (!pgd)
+		return;
+
+	/* pgd is always present and good */
+	pmd = pmd_off(pgd, 0);
+	if (pmd_none(*pmd))
+		goto free;
+	if (pmd_bad(*pmd)) {
+		pmd_ERROR(*pmd);
+		pmd_clear(pmd);
+		goto free;
+	}
+
+	pte = pmd_page(*pmd);
+	pmd_clear(pmd);
+	dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
+	pte_lock_deinit(pte);
+	pte_free(pte);
+	pmd_free(pmd);
+free:
+	free_pages((unsigned long) pgd, 2);
+}
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
new file mode 100644
index 0000000..4071381
--- /dev/null
+++ b/arch/arm/mm/proc-arm740.S
@@ -0,0 +1,174 @@
+/*
+ *  linux/arch/arm/mm/arm740.S: utility functions for ARM740
+ *
+ *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+	.text
+/*
+ * cpu_arm740_proc_init()
+ * cpu_arm740_do_idle()
+ * cpu_arm740_dcache_clean_area()
+ * cpu_arm740_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm740_proc_init)
+ENTRY(cpu_arm740_do_idle)
+ENTRY(cpu_arm740_dcache_clean_area)
+ENTRY(cpu_arm740_switch_mm)
+	mov	pc, lr
+
+/*
+ * cpu_arm740_proc_fin()
+ */
+ENTRY(cpu_arm740_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x3f000000		@ bank/f/lock/s
+	bic	r0, r0, #0x0000000c		@ w-buffer/cache
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	mcr	p15, 0, r0, c7, c0, 0		@ invalidate cache
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_arm740_reset(loc)
+ * Params  : r0 = address to jump to
+ * Notes   : This sets up everything for a reset
+ */
+ENTRY(cpu_arm740_reset)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c0, 0		@ invalidate cache
+	mrc	p15, 0, ip, c1, c0, 0		@ get ctrl register
+	bic	ip, ip, #0x0000000c		@ ............wc..
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	mov	pc, r0
+
+	__INIT
+
+	.type	__arm740_setup, #function
+__arm740_setup:
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c0, 0		@ invalidate caches
+
+	mcr	p15, 0, r0, c6, c3		@ disable area 3~7
+	mcr	p15, 0, r0, c6, c4
+	mcr	p15, 0, r0, c6, c5
+	mcr	p15, 0, r0, c6, c6
+	mcr	p15, 0, r0, c6, c7
+
+	mov	r0, #0x0000003F			@ base = 0, size = 4GB
+	mcr	p15, 0, r0, c6,	c0		@ set area 0, default
+
+	ldr	r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
+	ldr	r1, =(CONFIG_DRAM_SIZE >> 12)	@ size of RAM (must be >= 4KB)
+	mov	r2, #10				@ 11 is the minimum (4KB)
+1:	add	r2, r2, #1			@ area size *= 2
+	mov	r1, r1, lsr #1
+	bne	1b				@ count not zero r-shift
+	orr	r0, r0, r2, lsl #1		@ the area register value
+	orr	r0, r0, #1			@ set enable bit
+	mcr	p15, 0, r0, c6,	c1		@ set area 1, RAM
+
+	ldr	r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
+	ldr	r1, =(CONFIG_FLASH_SIZE >> 12)	@ size of FLASH (must be >= 4KB)
+	mov	r2, #10				@ 11 is the minimum (4KB)
+1:	add	r2, r2, #1			@ area size *= 2
+	mov	r1, r1, lsr #1
+	bne	1b				@ count not zero r-shift
+	orr	r0, r0, r2, lsl #1		@ the area register value
+	orr	r0, r0, #1			@ set enable bit
+	mcr	p15, 0, r0, c6,	c2		@ set area 2, ROM/FLASH
+
+	mov	r0, #0x06
+	mcr	p15, 0, r0, c2, c0		@ Region 1&2 cacheable
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mov	r0, #0x00			@ disable whole write buffer
+#else
+	mov	r0, #0x02			@ Region 1 write bufferred
+#endif
+	mcr	p15, 0, r0, c3, c0
+
+	mov	r0, #0x10000
+	sub	r0, r0, #1			@ r0 = 0xffff
+	mcr	p15, 0, r0, c5, c0		@ all read/write access
+
+	mrc	p15, 0, r0, c1, c0		@ get control register
+	bic	r0, r0, #0x3F000000		@ set to standard caching mode
+						@ need some benchmark
+	orr	r0, r0, #0x0000000d		@ MPU/Cache/WB
+
+	mov	pc, lr
+
+	.size	__arm740_setup, . - __arm740_setup
+
+	__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+	.type	arm740_processor_functions, #object
+ENTRY(arm740_processor_functions)
+	.word	v4t_late_abort
+	.word	cpu_arm740_proc_init
+	.word	cpu_arm740_proc_fin
+	.word	cpu_arm740_reset
+	.word   cpu_arm740_do_idle
+	.word	cpu_arm740_dcache_clean_area
+	.word	cpu_arm740_switch_mm
+	.word	0			@ cpu_*_set_pte
+	.size	arm740_processor_functions, . - arm740_processor_functions
+
+	.section ".rodata"
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv4"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v4"
+	.size	cpu_elf_name, . - cpu_elf_name
+
+	.type	cpu_arm740_name, #object
+cpu_arm740_name:
+	.ascii	"ARM740T"
+	.size	cpu_arm740_name, . - cpu_arm740_name
+
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+	.type	__arm740_proc_info,#object
+__arm740_proc_info:
+	.long	0x41807400
+	.long	0xfffffff0
+	.long	0
+	b	__arm740_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+	.long	cpu_arm740_name
+	.long	arm740_processor_functions
+	.long	0
+	.long	0
+	.long	v3_cache_fns			@ cache model
+	.size	__arm740_proc_info, . - __arm740_proc_info
+
+
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
new file mode 100644
index 0000000..22d7e31
--- /dev/null
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -0,0 +1,249 @@
+/*
+ *  linux/arch/arm/mm/proc-arm7tdmi.S: utility functions for ARM7TDMI
+ *
+ *  Copyright (C) 2003-2006 Hyok S. Choi <hyok.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+	.text
+/*
+ * cpu_arm7tdmi_proc_init()
+ * cpu_arm7tdmi_do_idle()
+ * cpu_arm7tdmi_dcache_clean_area()
+ * cpu_arm7tdmi_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm7tdmi_proc_init)
+ENTRY(cpu_arm7tdmi_do_idle)
+ENTRY(cpu_arm7tdmi_dcache_clean_area)
+ENTRY(cpu_arm7tdmi_switch_mm)
+		mov	pc, lr
+
+/*
+ * cpu_arm7tdmi_proc_fin()
+ */
+ENTRY(cpu_arm7tdmi_proc_fin)
+		mov	r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+		msr	cpsr_c, r0
+		mov	pc, lr
+
+/*
+ * Function: cpu_arm7tdmi_reset(loc)
+ * Params  : loc(r0)	address to jump to
+ * Purpose : Sets up everything for a reset and jump to the location for soft reset.
+ */
+ENTRY(cpu_arm7tdmi_reset)
+		mov	pc, r0
+
+		__INIT
+
+		.type	__arm7tdmi_setup, #function
+__arm7tdmi_setup:
+		mov	pc, lr
+		.size	__arm7tdmi_setup, . - __arm7tdmi_setup
+
+		__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+		.type	arm7tdmi_processor_functions, #object
+ENTRY(arm7tdmi_processor_functions)
+		.word	v4t_late_abort
+		.word	cpu_arm7tdmi_proc_init
+		.word	cpu_arm7tdmi_proc_fin
+		.word	cpu_arm7tdmi_reset
+		.word	cpu_arm7tdmi_do_idle
+		.word	cpu_arm7tdmi_dcache_clean_area
+		.word	cpu_arm7tdmi_switch_mm
+		.word	0		@ cpu_*_set_pte
+		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
+
+		.section ".rodata"
+
+		.type	cpu_arch_name, #object
+cpu_arch_name:
+		.asciz	"armv4t"
+		.size	cpu_arch_name, . - cpu_arch_name
+
+		.type	cpu_elf_name, #object
+cpu_elf_name:
+		.asciz	"v4"
+		.size	cpu_elf_name, . - cpu_elf_name
+
+		.type	cpu_arm7tdmi_name, #object
+cpu_arm7tdmi_name:
+		.asciz	"ARM7TDMI"
+		.size	cpu_arm7tdmi_name, . - cpu_arm7tdmi_name
+
+		.type	cpu_triscenda7_name, #object
+cpu_triscenda7_name:
+		.asciz	"Triscend-A7x"
+		.size	cpu_triscenda7_name, . - cpu_triscenda7_name
+
+		.type	cpu_at91_name, #object
+cpu_at91_name:
+		.asciz	"Atmel-AT91M40xxx"
+		.size	cpu_at91_name, . - cpu_at91_name
+
+		.type	cpu_s3c3410_name, #object
+cpu_s3c3410_name:
+		.asciz	"Samsung-S3C3410"
+		.size	cpu_s3c3410_name, . - cpu_s3c3410_name
+
+		.type	cpu_s3c44b0x_name, #object
+cpu_s3c44b0x_name:
+		.asciz	"Samsung-S3C44B0x"
+		.size	cpu_s3c44b0x_name, . - cpu_s3c44b0x_name
+
+		.type	cpu_s3c4510b, #object
+cpu_s3c4510b_name:
+		.asciz	"Samsung-S3C4510B"
+		.size	cpu_s3c4510b_name, . - cpu_s3c4510b_name
+
+		.type	cpu_s3c4530_name, #object
+cpu_s3c4530_name:
+		.asciz	"Samsung-S3C4530"
+		.size	cpu_s3c4530_name, . - cpu_s3c4530_name
+
+		.type	cpu_netarm_name, #object
+cpu_netarm_name:
+		.asciz	"NETARM"
+		.size	cpu_netarm_name, . - cpu_netarm_name
+
+		.align
+
+		.section ".proc.info.init", #alloc, #execinstr
+
+		.type	__arm7tdmi_proc_info, #object
+__arm7tdmi_proc_info:
+		.long	0x41007700
+		.long	0xfff8ff00
+		.long	0
+		.long	0
+		b	__arm7tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_26BIT
+		.long	cpu_arm7tdmi_name
+		.long	arm7tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__arm7tdmi_proc_info, . - __arm7dmi_proc_info
+
+		.type	__triscenda7_proc_info, #object
+__triscenda7_proc_info:
+		.long	0x0001d2ff
+		.long	0x0001ffff
+		.long	0
+		.long	0
+		b	__arm7tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_triscenda7_name
+		.long	arm7tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__triscenda7_proc_info, . - __triscenda7_proc_info
+
+		.type	__at91_proc_info, #object
+__at91_proc_info:
+		.long	0x14000040
+		.long	0xfff000e0
+		.long	0
+		.long	0
+		b	__arm7tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_at91_name
+		.long	arm7tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__at91_proc_info, . - __at91_proc_info
+
+		.type	__s3c4510b_proc_info, #object
+__s3c4510b_proc_info:
+		.long	0x36365000
+		.long	0xfffff000
+		.long	0
+		.long	0
+		b	__arm7tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_s3c4510b_name
+		.long	arm7tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__s3c4510b_proc_info, . - __s3c4510b_proc_info
+
+		.type	__s3c4530_proc_info, #object
+__s3c4530_proc_info:
+		.long	0x4c000000
+		.long	0xfff000e0
+		.long	0
+		.long	0
+		b	__arm7tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_s3c4530_name
+		.long	arm7tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__s3c4530_proc_info, . - __s3c4530_proc_info
+
+		.type	__s3c3410_proc_info, #object
+__s3c3410_proc_info:
+		.long	0x34100000
+		.long	0xffff0000
+		.long	0
+		.long	0
+		b	__arm7tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_s3c3410_name
+		.long	arm7tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__s3c3410_proc_info, . - __s3c3410_proc_info
+
+		.type	__s3c44b0x_proc_info, #object
+__s3c44b0x_proc_info:
+		.long	0x44b00000
+		.long	0xffff0000
+		.long	0
+		.long	0
+		b	__arm7tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_s3c44b0x_name
+		.long	arm7tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__s3c44b0x_proc_info, . - __s3c44b0x_proc_info
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
new file mode 100644
index 0000000..2397f4b6
--- /dev/null
+++ b/arch/arm/mm/proc-arm940.S
@@ -0,0 +1,369 @@
+/*
+ *  linux/arch/arm/mm/arm940.S: utility functions for ARM940T
+ *
+ *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+/* ARM940T has a 4KB DCache comprising 256 lines of 4 words */
+#define CACHE_DLINESIZE	16
+#define CACHE_DSEGMENTS	4
+#define CACHE_DENTRIES	64
+
+	.text
+/*
+ * cpu_arm940_proc_init()
+ * cpu_arm940_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm940_proc_init)
+ENTRY(cpu_arm940_switch_mm)
+	mov	pc, lr
+
+/*
+ * cpu_arm940_proc_fin()
+ */
+ENTRY(cpu_arm940_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+	bl	arm940_flush_kern_cache_all
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x00001000		@ i-cache
+	bic	r0, r0, #0x00000004		@ d-cache
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_arm940_reset(loc)
+ * Params  : r0 = address to jump to
+ * Notes   : This sets up everything for a reset
+ */
+ENTRY(cpu_arm940_reset)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c5, 0		@ flush I cache
+	mcr	p15, 0, ip, c7, c6, 0		@ flush D cache
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x00000005		@ .............c.p
+	bic	ip, ip, #0x00001000		@ i-cache
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	mov	pc, r0
+
+/*
+ * cpu_arm940_do_idle()
+ */
+	.align	5
+ENTRY(cpu_arm940_do_idle)
+	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_all()
+ */
+ENTRY(arm940_flush_user_cache_all)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(arm940_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	/* FALLTHROUGH */
+
+/*
+ *	flush_user_cache_range(start, end, flags)
+ *
+ *	There is no efficient way to flush a range of cache entries
+ *	in the specified address range. Thus, flushes all.
+ *
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags describing address space
+ */
+ENTRY(arm940_flush_user_cache_range)
+	mov	ip, #0
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ flush D cache
+#else
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 4	@ 4 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean/flush D index
+	subs	r3, r3, #1 << 26
+	bcs	2b				@ entries 63 to 0
+	subs	r1, r1, #1 << 4
+	bcs	1b				@ segments 3 to 0
+#endif
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm940_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm940_coherent_user_range)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(arm940_flush_kern_dcache_page)
+	mov	ip, #0
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 4	@ 4 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean/flush D index
+	subs	r3, r3, #1 << 26
+	bcs	2b				@ entries 63 to 0
+	subs	r1, r1, #1 << 4
+	bcs	1b				@ segments 7 to 0
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	There is no efficient way to invalidate a specifid virtual
+ *	address range. Thus, invalidates all.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm940_dma_inv_range)
+	mov	ip, #0
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 4	@ 4 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:	mcr	p15, 0, r3, c7, c6, 2		@ flush D entry
+	subs	r3, r3, #1 << 26
+	bcs	2b				@ entries 63 to 0
+	subs	r1, r1, #1 << 4
+	bcs	1b				@ segments 7 to 0
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	There is no efficient way to clean a specifid virtual
+ *	address range. Thus, cleans all.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm940_dma_clean_range)
+ENTRY(cpu_arm940_dcache_clean_area)
+	mov	ip, #0
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 4	@ 4 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:	mcr	p15, 0, r3, c7, c10, 2		@ clean D entry
+	subs	r3, r3, #1 << 26
+	bcs	2b				@ entries 63 to 0
+	subs	r1, r1, #1 << 4
+	bcs	1b				@ segments 7 to 0
+#endif
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	There is no efficient way to clean and invalidate a specifid
+ *	virtual address range.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm940_dma_flush_range)
+	mov	ip, #0
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 4	@ 4 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r3, c7, c14, 2		@ clean/flush D entry
+#else
+	mcr	p15, 0, r3, c7, c10, 2		@ clean D entry
+#endif
+	subs	r3, r3, #1 << 26
+	bcs	2b				@ entries 63 to 0
+	subs	r1, r1, #1 << 4
+	bcs	1b				@ segments 7 to 0
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+ENTRY(arm940_cache_fns)
+	.long	arm940_flush_kern_cache_all
+	.long	arm940_flush_user_cache_all
+	.long	arm940_flush_user_cache_range
+	.long	arm940_coherent_kern_range
+	.long	arm940_coherent_user_range
+	.long	arm940_flush_kern_dcache_page
+	.long	arm940_dma_inv_range
+	.long	arm940_dma_clean_range
+	.long	arm940_dma_flush_range
+
+	__INIT
+
+	.type	__arm940_setup, #function
+__arm940_setup:
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c6, 0		@ invalidate D cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+
+	mcr	p15, 0, r0, c6, c3, 0		@ disable data area 3~7
+	mcr	p15, 0, r0, c6, c4, 0
+	mcr	p15, 0, r0, c6, c5, 0
+	mcr	p15, 0, r0, c6, c6, 0
+	mcr	p15, 0, r0, c6, c7, 0
+
+	mcr	p15, 0, r0, c6, c3, 1		@ disable instruction area 3~7
+	mcr	p15, 0, r0, c6, c4, 1
+	mcr	p15, 0, r0, c6, c5, 1
+	mcr	p15, 0, r0, c6, c6, 1
+	mcr	p15, 0, r0, c6, c7, 1
+
+	mov	r0, #0x0000003F			@ base = 0, size = 4GB
+	mcr	p15, 0, r0, c6,	c0, 0		@ set area 0, default
+	mcr	p15, 0, r0, c6,	c0, 1
+
+	ldr	r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
+	ldr	r1, =(CONFIG_DRAM_SIZE >> 12)	@ size of RAM (must be >= 4KB)
+	mov	r2, #10				@ 11 is the minimum (4KB)
+1:	add	r2, r2, #1			@ area size *= 2
+	mov	r1, r1, lsr #1
+	bne	1b				@ count not zero r-shift
+	orr	r0, r0, r2, lsl #1		@ the area register value
+	orr	r0, r0, #1			@ set enable bit
+	mcr	p15, 0, r0, c6,	c1, 0		@ set area 1, RAM
+	mcr	p15, 0, r0, c6,	c1, 1
+
+	ldr	r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
+	ldr	r1, =(CONFIG_FLASH_SIZE >> 12)	@ size of FLASH (must be >= 4KB)
+	mov	r2, #10				@ 11 is the minimum (4KB)
+1:	add	r2, r2, #1			@ area size *= 2
+	mov	r1, r1, lsr #1
+	bne	1b				@ count not zero r-shift
+	orr	r0, r0, r2, lsl #1		@ the area register value
+	orr	r0, r0, #1			@ set enable bit
+	mcr	p15, 0, r0, c6,	c2, 0		@ set area 2, ROM/FLASH
+	mcr	p15, 0, r0, c6,	c2, 1
+
+	mov	r0, #0x06
+	mcr	p15, 0, r0, c2, c0, 0		@ Region 1&2 cacheable
+	mcr	p15, 0, r0, c2, c0, 1
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mov	r0, #0x00			@ disable whole write buffer
+#else
+	mov	r0, #0x02			@ Region 1 write bufferred
+#endif
+	mcr	p15, 0, r0, c3, c0, 0
+
+	mov	r0, #0x10000
+	sub	r0, r0, #1			@ r0 = 0xffff
+	mcr	p15, 0, r0, c5, c0, 0		@ all read/write access
+	mcr	p15, 0, r0, c5, c0, 1
+
+	mrc	p15, 0, r0, c1, c0		@ get control register
+	orr	r0, r0, #0x00001000		@ I-cache
+	orr	r0, r0, #0x00000005		@ MPU/D-cache
+
+	mov	pc, lr
+
+	.size	__arm940_setup, . - __arm940_setup
+
+	__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+	.type	arm940_processor_functions, #object
+ENTRY(arm940_processor_functions)
+	.word	nommu_early_abort
+	.word	cpu_arm940_proc_init
+	.word	cpu_arm940_proc_fin
+	.word	cpu_arm940_reset
+	.word   cpu_arm940_do_idle
+	.word	cpu_arm940_dcache_clean_area
+	.word	cpu_arm940_switch_mm
+	.word	0		@ cpu_*_set_pte
+	.size	arm940_processor_functions, . - arm940_processor_functions
+
+	.section ".rodata"
+
+.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv4t"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v4"
+	.size	cpu_elf_name, . - cpu_elf_name
+
+	.type	cpu_arm940_name, #object
+cpu_arm940_name:
+	.ascii	"ARM940T"
+	.size	cpu_arm940_name, . - cpu_arm940_name
+
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	.type	__arm940_proc_info,#object
+__arm940_proc_info:
+	.long	0x41009400
+	.long	0xff00fff0
+	.long	0
+	b	__arm940_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	cpu_arm940_name
+	.long	arm940_processor_functions
+	.long	0
+	.long	0
+	.long	arm940_cache_fns
+	.size	__arm940_proc_info, . - __arm940_proc_info
+
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
new file mode 100644
index 0000000..e186175
--- /dev/null
+++ b/arch/arm/mm/proc-arm946.S
@@ -0,0 +1,424 @@
+/*
+ *  linux/arch/arm/mm/arm946.S: utility functions for ARM946E-S
+ *
+ *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com)
+ *
+ *  (Many of cache codes are from proc-arm926.S)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+/*
+ * ARM946E-S is synthesizable to have 0KB to 1MB sized D-Cache,
+ * comprising 256 lines of 32 bytes (8 words).
+ */
+#define CACHE_DSIZE	(CONFIG_CPU_DCACHE_SIZE) /* typically 8KB. */
+#define CACHE_DLINESIZE	32			/* fixed */
+#define CACHE_DSEGMENTS	4			/* fixed */
+#define CACHE_DENTRIES	(CACHE_DSIZE / CACHE_DSEGMENTS / CACHE_DLINESIZE)
+#define CACHE_DLIMIT	(CACHE_DSIZE * 4)	/* benchmark needed */
+
+	.text
+/*
+ * cpu_arm946_proc_init()
+ * cpu_arm946_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm946_proc_init)
+ENTRY(cpu_arm946_switch_mm)
+	mov	pc, lr
+
+/*
+ * cpu_arm946_proc_fin()
+ */
+ENTRY(cpu_arm946_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+	bl	arm946_flush_kern_cache_all
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x00001000		@ i-cache
+	bic	r0, r0, #0x00000004		@ d-cache
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_arm946_reset(loc)
+ * Params  : r0 = address to jump to
+ * Notes   : This sets up everything for a reset
+ */
+ENTRY(cpu_arm946_reset)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c5, 0		@ flush I cache
+	mcr	p15, 0, ip, c7, c6, 0		@ flush D cache
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x00000005		@ .............c.p
+	bic	ip, ip, #0x00001000		@ i-cache
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	mov	pc, r0
+
+/*
+ * cpu_arm946_do_idle()
+ */
+	.align	5
+ENTRY(cpu_arm946_do_idle)
+	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_all()
+ */
+ENTRY(arm946_flush_user_cache_all)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(arm946_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ flush D cache
+#else
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 29 @ 4 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 4 @ n entries
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean/flush D index
+	subs	r3, r3, #1 << 4
+	bcs	2b				@ entries n to 0
+	subs	r1, r1, #1 << 29
+	bcs	1b				@ segments 3 to 0
+#endif
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 0		@ flush I cache
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, flags)
+ *
+ *	Clean and invalidate a range of cache entries in the
+ *	specified address range.
+ *
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags describing address space
+ * (same as arm926)
+ */
+ENTRY(arm946_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bhs	__flush_whole_cache
+
+1:	tst	r2, #VM_EXEC
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+#else
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+#endif
+	cmp	r0, r1
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm946_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ * (same as arm926)
+ */
+ENTRY(arm946_coherent_user_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ * (same as arm926)
+ */
+ENTRY(arm946_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ * (same as arm926)
+ */
+ENTRY(arm946_dma_inv_range)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	tst	r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+#endif
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean the specified virtual address range.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as arm926)
+ */
+ENTRY(arm946_dma_clean_range)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+#endif
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as arm926)
+ */
+ENTRY(arm946_dma_flush_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+#else
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+#endif
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+ENTRY(arm946_cache_fns)
+	.long	arm946_flush_kern_cache_all
+	.long	arm946_flush_user_cache_all
+	.long	arm946_flush_user_cache_range
+	.long	arm946_coherent_kern_range
+	.long	arm946_coherent_user_range
+	.long	arm946_flush_kern_dcache_page
+	.long	arm946_dma_inv_range
+	.long	arm946_dma_clean_range
+	.long	arm946_dma_flush_range
+
+
+ENTRY(cpu_arm946_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+#endif
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+	__INIT
+
+	.type	__arm946_setup, #function
+__arm946_setup:
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c6, 0		@ invalidate D cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+
+	mcr	p15, 0, r0, c6, c3, 0		@ disable memory region 3~7
+	mcr	p15, 0, r0, c6, c4, 0
+	mcr	p15, 0, r0, c6, c5, 0
+	mcr	p15, 0, r0, c6, c6, 0
+	mcr	p15, 0, r0, c6, c7, 0
+
+	mov	r0, #0x0000003F			@ base = 0, size = 4GB
+	mcr	p15, 0, r0, c6,	c0, 0		@ set region 0, default
+
+	ldr	r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
+	ldr	r1, =(CONFIG_DRAM_SIZE >> 12)	@ size of RAM (must be >= 4KB)
+	mov	r2, #10				@ 11 is the minimum (4KB)
+1:	add	r2, r2, #1			@ area size *= 2
+	mov	r1, r1, lsr #1
+	bne	1b				@ count not zero r-shift
+	orr	r0, r0, r2, lsl #1		@ the region register value
+	orr	r0, r0, #1			@ set enable bit
+	mcr	p15, 0, r0, c6,	c1, 0		@ set region 1, RAM
+
+	ldr	r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
+	ldr	r1, =(CONFIG_FLASH_SIZE >> 12)	@ size of FLASH (must be >= 4KB)
+	mov	r2, #10				@ 11 is the minimum (4KB)
+1:	add	r2, r2, #1			@ area size *= 2
+	mov	r1, r1, lsr #1
+	bne	1b				@ count not zero r-shift
+	orr	r0, r0, r2, lsl #1		@ the region register value
+	orr	r0, r0, #1			@ set enable bit
+	mcr	p15, 0, r0, c6,	c2, 0		@ set region 2, ROM/FLASH
+
+	mov	r0, #0x06
+	mcr	p15, 0, r0, c2, c0, 0		@ region 1,2 d-cacheable
+	mcr	p15, 0, r0, c2, c0, 1		@ region 1,2 i-cacheable
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mov	r0, #0x00			@ disable whole write buffer
+#else
+	mov	r0, #0x02			@ region 1 write bufferred
+#endif
+	mcr	p15, 0, r0, c3, c0, 0
+
+/*
+ *  Access Permission Settings for future permission control by PU.
+ *
+ *				priv.	user
+ * 	region 0 (whole)	rw	--	: b0001
+ * 	region 1 (RAM)		rw	rw	: b0011
+ * 	region 2 (FLASH)	rw	r-	: b0010
+ *	region 3~7 (none)	--	--	: b0000
+ */
+	mov	r0, #0x00000031
+	orr	r0, r0, #0x00000200
+	mcr	p15, 0, r0, c5, c0, 2		@ set data access permission
+	mcr	p15, 0, r0, c5, c0, 3		@ set inst. access permission
+
+	mrc	p15, 0, r0, c1, c0		@ get control register
+	orr	r0, r0, #0x00001000		@ I-cache
+	orr	r0, r0, #0x00000005		@ MPU/D-cache
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
+	orr	r0, r0, #0x00004000		@ .1.. .... .... ....
+#endif
+	mov	pc, lr
+
+	.size	__arm946_setup, . - __arm946_setup
+
+	__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+	.type	arm946_processor_functions, #object
+ENTRY(arm946_processor_functions)
+	.word	nommu_early_abort
+	.word	cpu_arm946_proc_init
+	.word	cpu_arm946_proc_fin
+	.word	cpu_arm946_reset
+	.word   cpu_arm946_do_idle
+
+	.word	cpu_arm946_dcache_clean_area
+	.word	cpu_arm946_switch_mm
+	.word	0		@ cpu_*_set_pte
+	.size	arm946_processor_functions, . - arm946_processor_functions
+
+	.section ".rodata"
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv5te"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v5t"
+	.size	cpu_elf_name, . - cpu_elf_name
+
+	.type	cpu_arm946_name, #object
+cpu_arm946_name:
+	.ascii	"ARM946E-S"
+	.size	cpu_arm946_name, . - cpu_arm946_name
+
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+	.type	__arm946_proc_info,#object
+__arm946_proc_info:
+	.long	0x41009460
+	.long	0xff00fff0
+	.long	0
+	b	__arm946_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	cpu_arm946_name
+	.long	arm946_processor_functions
+	.long	0
+	.long	0
+	.long	arm940_cache_fns
+	.size	__arm946_proc_info, . - __arm946_proc_info
+
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
new file mode 100644
index 0000000..918ebf6
--- /dev/null
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -0,0 +1,134 @@
+/*
+ *  linux/arch/arm/mm/proc-arm9tdmi.S: utility functions for ARM9TDMI
+ *
+ *  Copyright (C) 2003-2006 Hyok S. Choi <hyok.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+	.text
+/*
+ * cpu_arm9tdmi_proc_init()
+ * cpu_arm9tdmi_do_idle()
+ * cpu_arm9tdmi_dcache_clean_area()
+ * cpu_arm9tdmi_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm9tdmi_proc_init)
+ENTRY(cpu_arm9tdmi_do_idle)
+ENTRY(cpu_arm9tdmi_dcache_clean_area)
+ENTRY(cpu_arm9tdmi_switch_mm)
+		mov	pc, lr
+
+/*
+ * cpu_arm9tdmi_proc_fin()
+ */
+ENTRY(cpu_arm9tdmi_proc_fin)
+		mov	r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+		msr	cpsr_c, r0
+		mov	pc, lr
+
+/*
+ * Function: cpu_arm9tdmi_reset(loc)
+ * Params  : loc(r0)	address to jump to
+ * Purpose : Sets up everything for a reset and jump to the location for soft reset.
+ */
+ENTRY(cpu_arm9tdmi_reset)
+		mov	pc, r0
+
+		__INIT
+
+		.type	__arm9tdmi_setup, #function
+__arm9tdmi_setup:
+		mov	pc, lr
+		.size	__arm9tdmi_setup, . - __arm9tdmi_setup
+
+		__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+		.type	arm9tdmi_processor_functions, #object
+ENTRY(arm9tdmi_processor_functions)
+		.word	nommu_early_abort
+		.word	cpu_arm9tdmi_proc_init
+		.word	cpu_arm9tdmi_proc_fin
+		.word	cpu_arm9tdmi_reset
+		.word	cpu_arm9tdmi_do_idle
+		.word	cpu_arm9tdmi_dcache_clean_area
+		.word	cpu_arm9tdmi_switch_mm
+		.word	0		@ cpu_*_set_pte
+		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
+
+		.section ".rodata"
+
+		.type	cpu_arch_name, #object
+cpu_arch_name:
+		.asciz	"armv4t"
+		.size	cpu_arch_name, . - cpu_arch_name
+
+		.type	cpu_elf_name, #object
+cpu_elf_name:
+		.asciz	"v4"
+		.size	cpu_elf_name, . - cpu_elf_name
+
+		.type	cpu_arm9tdmi_name, #object
+cpu_arm9tdmi_name:
+		.asciz	"ARM9TDMI"
+		.size	cpu_arm9tdmi_name, . - cpu_arm9tdmi_name
+
+		.type	cpu_p2001_name, #object
+cpu_p2001_name:
+		.asciz	"P2001"
+		.size	cpu_p2001_name, . - cpu_p2001_name
+
+		.align
+
+		.section ".proc.info.init", #alloc, #execinstr
+
+		.type	__arm9tdmi_proc_info, #object
+__arm9tdmi_proc_info:
+		.long	0x41009900
+		.long	0xfff8ff00
+		.long	0
+		.long	0
+		b	__arm9tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_arm9tdmi_name
+		.long	arm9tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__arm9tdmi_proc_info, . - __arm9dmi_proc_info
+
+		.type	__p2001_proc_info, #object
+__p2001_proc_info:
+		.long	0x41029000
+		.long	0xffffffff
+		.long	0
+		.long	0
+		b	__arm9tdmi_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+		.long	cpu_p2001_name
+		.long	arm9tdmi_processor_functions
+		.long	0
+		.long	0
+		.long	v4_cache_fns
+		.size	__p2001_proc_info, . - __p2001_proc_info
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 3ca0c92..e8b377d 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -311,12 +311,6 @@
  *	- end	 - virtual end address
  */
 ENTRY(xscale_dma_inv_range)
-	mrc	p15, 0, r2, c0, c0, 0		@ read ID
-	eor	r2, r2, #0x69000000
-	eor	r2, r2, #0x00052000
-	bics	r2, r2, #1
-	beq	xscale_dma_flush_range
-
 	tst	r0, #CACHELINESIZE - 1
 	bic	r0, r0, #CACHELINESIZE - 1
 	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
@@ -375,6 +369,30 @@
 	.long	xscale_dma_clean_range
 	.long	xscale_dma_flush_range
 
+/*
+ * On stepping A0/A1 of the 80200, invalidating D-cache by line doesn't
+ * clear the dirty bits, which means that if we invalidate a dirty line,
+ * the dirty data can still be written back to external memory later on.
+ *
+ * The recommended workaround is to always do a clean D-cache line before
+ * doing an invalidate D-cache line, so on the affected processors,
+ * dma_inv_range() is implemented as dma_flush_range().
+ *
+ * See erratum #25 of "Intel 80200 Processor Specification Update",
+ * revision January 22, 2003, available at:
+ *     http://www.intel.com/design/iio/specupdt/273415.htm
+ */
+ENTRY(xscale_80200_A0_A1_cache_fns)
+	.long	xscale_flush_kern_cache_all
+	.long	xscale_flush_user_cache_all
+	.long	xscale_flush_user_cache_range
+	.long	xscale_coherent_kern_range
+	.long	xscale_coherent_user_range
+	.long	xscale_flush_kern_dcache_page
+	.long	xscale_dma_flush_range
+	.long	xscale_dma_clean_range
+	.long	xscale_dma_flush_range
+
 ENTRY(cpu_xscale_dcache_clean_area)
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #CACHELINESIZE
@@ -531,6 +549,11 @@
 	.asciz	"v5"
 	.size	cpu_elf_name, . - cpu_elf_name
 
+	.type	cpu_80200_A0_A1_name, #object
+cpu_80200_A0_A1_name:
+	.asciz	"XScale-80200 A0/A1"
+	.size	cpu_80200_A0_A1_name, . - cpu_80200_A0_A1_name
+
 	.type	cpu_80200_name, #object
 cpu_80200_name:
 	.asciz	"XScale-80200"
@@ -595,6 +618,29 @@
 
 	.section ".proc.info.init", #alloc, #execinstr
 
+	.type	__80200_A0_A1_proc_info,#object
+__80200_A0_A1_proc_info:
+	.long	0x69052000
+	.long	0xfffffffe
+	.long   PMD_TYPE_SECT | \
+		PMD_SECT_BUFFERABLE | \
+		PMD_SECT_CACHEABLE | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	.long   PMD_TYPE_SECT | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_80200_name
+	.long	xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_80200_A0_A1_cache_fns
+	.size	__80200_A0_A1_proc_info, . - __80200_A0_A1_proc_info
+
 	.type	__80200_proc_info,#object
 __80200_proc_info:
 	.long	0x69052000
diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c
index 34fdc73..6576143 100644
--- a/arch/arm/oprofile/op_model_xscale.c
+++ b/arch/arm/oprofile/op_model_xscale.c
@@ -36,11 +36,11 @@
 #ifdef CONFIG_ARCH_IOP310
 #define XSCALE_PMU_IRQ  IRQ_XS80200_PMU
 #endif
-#ifdef CONFIG_ARCH_IOP321
-#define XSCALE_PMU_IRQ  IRQ_IOP321_CORE_PMU
+#ifdef CONFIG_ARCH_IOP32X
+#define XSCALE_PMU_IRQ  IRQ_IOP32X_CORE_PMU
 #endif
-#ifdef CONFIG_ARCH_IOP331
-#define XSCALE_PMU_IRQ  IRQ_IOP331_CORE_PMU
+#ifdef CONFIG_ARCH_IOP33X
+#define XSCALE_PMU_IRQ  IRQ_IOP33X_CORE_PMU
 #endif
 #ifdef CONFIG_ARCH_PXA
 #define XSCALE_PMU_IRQ  IRQ_PMU
@@ -88,7 +88,7 @@
 /*
  * There are two versions of the PMU in current XScale processors
  * with differing register layouts and number of performance counters.
- * e.g. IOP321 is xsc1 whilst IOP331 is xsc2.
+ * e.g. IOP32x is xsc1 whilst IOP33x is xsc2.
  * We detect which register layout to use in xscale_detect_pmu()
  */
 enum { PMU_XSC1, PMU_XSC2 };
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
new file mode 100644
index 0000000..23da00b
--- /dev/null
+++ b/arch/arm/plat-iop/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y			:= gpio.o i2c.o pci.o setup.o time.o
+obj-m			:=
+obj-n			:=
+obj-			:=
diff --git a/arch/arm/plat-iop/gpio.c b/arch/arm/plat-iop/gpio.c
new file mode 100644
index 0000000..eda4360
--- /dev/null
+++ b/arch/arm/plat-iop/gpio.c
@@ -0,0 +1,48 @@
+/*
+ * arch/arm/plat-iop/gpio.c
+ * GPIO handling for Intel IOP3xx processors.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/device.h>
+#include <asm/hardware/iop3xx.h>
+
+void gpio_line_config(int line, int direction)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (direction == GPIO_IN) {
+		*IOP3XX_GPOE |= 1 << line;
+	} else if (direction == GPIO_OUT) {
+		*IOP3XX_GPOE &= ~(1 << line);
+	}
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_line_config);
+
+int gpio_line_get(int line)
+{
+	return !!(*IOP3XX_GPID & (1 << line));
+}
+EXPORT_SYMBOL(gpio_line_get);
+
+void gpio_line_set(int line, int value)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (value == GPIO_LOW) {
+		*IOP3XX_GPOD &= ~(1 << line);
+	} else if (value == GPIO_HIGH) {
+		*IOP3XX_GPOD |= 1 << line;
+	}
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_line_set);
diff --git a/arch/arm/plat-iop/i2c.c b/arch/arm/plat-iop/i2c.c
new file mode 100644
index 0000000..e99909b
--- /dev/null
+++ b/arch/arm/plat-iop/i2c.c
@@ -0,0 +1,81 @@
+/*
+ * arch/arm/plat-iop/i2c.c
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ * Copyright (C) 2004 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop3xx.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#ifdef CONFIG_ARCH_IOP32X
+#define IRQ_IOP3XX_I2C_0	IRQ_IOP32X_I2C_0
+#define IRQ_IOP3XX_I2C_1	IRQ_IOP32X_I2C_1
+#endif
+#ifdef CONFIG_ARCH_IOP33X
+#define IRQ_IOP3XX_I2C_0	IRQ_IOP33X_I2C_0
+#define IRQ_IOP3XX_I2C_1	IRQ_IOP33X_I2C_1
+#endif
+
+static struct resource iop3xx_i2c0_resources[] = {
+	[0] = {
+		.start	= 0xfffff680,
+		.end	= 0xfffff697,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_IOP3XX_I2C_0,
+		.end	= IRQ_IOP3XX_I2C_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device iop3xx_i2c0_device = {
+	.name		= "IOP3xx-I2C",
+	.id		= 0,
+	.num_resources	= 2,
+	.resource	= iop3xx_i2c0_resources,
+};
+
+
+static struct resource iop3xx_i2c1_resources[] = {
+	[0] = {
+		.start	= 0xfffff6a0,
+		.end	= 0xfffff6b7,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_IOP3XX_I2C_1,
+		.end	= IRQ_IOP3XX_I2C_1,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device iop3xx_i2c1_device = {
+	.name		= "IOP3xx-I2C",
+	.id		= 1,
+	.num_resources	= 2,
+	.resource	= iop3xx_i2c1_resources,
+};
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
new file mode 100644
index 0000000..e647812
--- /dev/null
+++ b/arch/arm/plat-iop/pci.c
@@ -0,0 +1,247 @@
+/*
+ * arch/arm/plat-iop/pci.c
+ *
+ * PCI support for the Intel IOP32X and IOP33X processors
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach/pci.h>
+#include <asm/hardware/iop3xx.h>
+
+// #define DEBUG
+
+#ifdef DEBUG
+#define  DBG(x...) printk(x)
+#else
+#define  DBG(x...) do { } while (0)
+#endif
+
+/*
+ * This routine builds either a type0 or type1 configuration command.  If the
+ * bus is on the 803xx then a type0 made, else a type1 is created.
+ */
+static u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	u32 addr;
+
+	if (sys->busnr == bus->number)
+		addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
+	else
+		addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
+
+	addr |=	PCI_FUNC(devfn) << 8 | (where & ~3);
+
+	return addr;
+}
+
+/*
+ * This routine checks the status of the last configuration cycle.  If an error
+ * was detected it returns a 1, else it returns a 0.  The errors being checked
+ * are parity, master abort, target abort (master and target).  These types of
+ * errors occure during a config cycle where there is no device, like during
+ * the discovery stage.
+ */
+static int iop3xx_pci_status(void)
+{
+	unsigned int status;
+	int ret = 0;
+
+	/*
+	 * Check the status registers.
+	 */
+	status = *IOP3XX_ATUSR;
+	if (status & 0xf900) {
+		DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
+		*IOP3XX_ATUSR = status & 0xf900;
+		ret = 1;
+	}
+
+	status = *IOP3XX_ATUISR;
+	if (status & 0x679f) {
+		DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
+		*IOP3XX_ATUISR = status & 0x679f;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+/*
+ * Simply write the address register and read the configuration
+ * data.  Note that the 4 nop's ensure that we are able to handle
+ * a delayed abort (in theory.)
+ */
+static inline u32 iop3xx_read(unsigned long addr)
+{
+	u32 val;
+
+	__asm__ __volatile__(
+		"str	%1, [%2]\n\t"
+		"ldr	%0, [%3]\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		: "=r" (val)
+		: "r" (addr), "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR));
+
+	return val;
+}
+
+/*
+ * The read routines must check the error status of the last configuration
+ * cycle.  If there was an error, the routine returns all hex f's.
+ */
+static int
+iop3xx_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		int size, u32 *value)
+{
+	unsigned long addr = iop3xx_cfg_address(bus, devfn, where);
+	u32 val = iop3xx_read(addr) >> ((where & 3) * 8);
+
+	if (iop3xx_pci_status())
+		val = 0xffffffff;
+
+	*value = val;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop3xx_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		int size, u32 value)
+{
+	unsigned long addr = iop3xx_cfg_address(bus, devfn, where);
+	u32 val;
+
+	if (size != 4) {
+		val = iop3xx_read(addr);
+		if (iop3xx_pci_status())
+			return PCIBIOS_SUCCESSFUL;
+
+		where = (where & 3) * 8;
+
+		if (size == 1)
+			val &= ~(0xff << where);
+		else
+			val &= ~(0xffff << where);
+
+		*IOP3XX_OCCDR = val | value << where;
+	} else {
+		asm volatile(
+			"str	%1, [%2]\n\t"
+			"str	%0, [%3]\n\t"
+			"nop\n\t"
+			"nop\n\t"
+			"nop\n\t"
+			"nop\n\t"
+			:
+			: "r" (value), "r" (addr),
+			  "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR));
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop3xx_ops = {
+	.read	= iop3xx_read_config,
+	.write	= iop3xx_write_config,
+};
+
+/*
+ * When a PCI device does not exist during config cycles, the 80200 gets a
+ * bus error instead of returning 0xffffffff. This handler simply returns.
+ */
+static int
+iop3xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
+		addr, fsr, regs->ARM_pc, regs->ARM_lr);
+
+	/*
+	 * If it was an imprecise abort, then we need to correct the
+	 * return address to be _after_ the instruction.
+	 */
+	if (fsr & (1 << 10))
+		regs->ARM_pc += 4;
+
+	return 0;
+}
+
+int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	struct resource *res;
+
+	if (nr != 0)
+		return 0;
+
+	res = kzalloc(2 * sizeof(struct resource), GFP_KERNEL);
+	if (!res)
+		panic("PCI: unable to alloc resources");
+
+	res[0].start = IOP3XX_PCI_LOWER_IO_VA;
+	res[0].end   = IOP3XX_PCI_LOWER_IO_VA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
+	res[0].name  = "IOP3XX PCI I/O Space";
+	res[0].flags = IORESOURCE_IO;
+	request_resource(&ioport_resource, &res[0]);
+
+	res[1].start = IOP3XX_PCI_LOWER_MEM_PA;
+	res[1].end   = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1;
+	res[1].name  = "IOP3XX PCI Memory Space";
+	res[1].flags = IORESOURCE_MEM;
+	request_resource(&iomem_resource, &res[1]);
+
+	sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
+	sys->io_offset  = IOP3XX_PCI_LOWER_IO_VA - IOP3XX_PCI_LOWER_IO_BA;
+
+	sys->resource[0] = &res[0];
+	sys->resource[1] = &res[1];
+	sys->resource[2] = NULL;
+
+	return 1;
+}
+
+struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &iop3xx_ops, sys);
+}
+
+void iop3xx_pci_preinit(void)
+{
+	DBG("PCI:  Intel 803xx PCI init code.\n");
+	DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
+	DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n",
+			*IOP3XX_OMWTVR0,
+			*IOP3XX_OIOWTVR);
+	DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR);
+	DBG("ATU: IOP3XX_IABAR0=0x%08x IOP3XX_IALR0=0x%08x IOP3XX_IATVR0=%08x\n",
+			*IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0);
+	DBG("ATU: IOP3XX_OMWTVR0=0x%08x\n", *IOP3XX_OMWTVR0);
+	DBG("ATU: IOP3XX_IABAR1=0x%08x IOP3XX_IALR1=0x%08x\n",
+			*IOP3XX_IABAR1, *IOP3XX_IALR1);
+	DBG("ATU: IOP3XX_ERBAR=0x%08x IOP3XX_ERLR=0x%08x IOP3XX_ERTVR=%08x\n",
+			*IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR);
+	DBG("ATU: IOP3XX_IABAR2=0x%08x IOP3XX_IALR2=0x%08x IOP3XX_IATVR2=%08x\n",
+			*IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2);
+	DBG("ATU: IOP3XX_IABAR3=0x%08x IOP3XX_IALR3=0x%08x IOP3XX_IATVR3=%08x\n",
+			*IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3);
+
+	hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort");
+}
diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/plat-iop/setup.c
new file mode 100644
index 0000000..4689db6
--- /dev/null
+++ b/arch/arm/plat-iop/setup.c
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/plat-iop/setup.c
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ * Copyright (C) 2004 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/iop3xx.h>
+
+/*
+ * Standard IO mapping for all IOP3xx based systems
+ */
+static struct map_desc iop3xx_std_desc[] __initdata = {
+	 {	/* mem mapped registers */
+		.virtual	= IOP3XX_PERIPHERAL_VIRT_BASE,
+		.pfn		= __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE),
+		.length		= IOP3XX_PERIPHERAL_SIZE,
+		.type		= MT_DEVICE,
+	 }, {	/* PCI IO space */
+		.virtual	= IOP3XX_PCI_LOWER_IO_VA,
+		.pfn		= __phys_to_pfn(IOP3XX_PCI_LOWER_IO_PA),
+		.length		= IOP3XX_PCI_IO_WINDOW_SIZE,
+		.type		= MT_DEVICE,
+	 },
+};
+
+void __init iop3xx_map_io(void)
+{
+	iotable_init(iop3xx_std_desc, ARRAY_SIZE(iop3xx_std_desc));
+}
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
new file mode 100644
index 0000000..06282df
--- /dev/null
+++ b/arch/arm/plat-iop/time.c
@@ -0,0 +1,98 @@
+/*
+ * arch/arm/plat-iop/time.c
+ *
+ * Timer code for IOP32x and IOP33x based systems
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright 2002-2003 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/timex.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#ifdef CONFIG_ARCH_IOP32X
+#define IRQ_IOP3XX_TIMER0	IRQ_IOP32X_TIMER0
+#else
+#ifdef CONFIG_ARCH_IOP33X
+#define IRQ_IOP3XX_TIMER0	IRQ_IOP33X_TIMER0
+#endif
+#endif
+
+static unsigned long ticks_per_jiffy;
+static unsigned long ticks_per_usec;
+static unsigned long next_jiffy_time;
+
+unsigned long iop3xx_gettimeoffset(void)
+{
+	unsigned long offset;
+
+	offset = next_jiffy_time - *IOP3XX_TU_TCR1;
+
+	return offset / ticks_per_usec;
+}
+
+static irqreturn_t
+iop3xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (1));
+	iop3xx_cp6_disable();
+
+	while ((signed long)(next_jiffy_time - *IOP3XX_TU_TCR1)
+							>= ticks_per_jiffy) {
+		timer_tick(regs);
+		next_jiffy_time -= ticks_per_jiffy;
+	}
+
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction iop3xx_timer_irq = {
+	.name		= "IOP3XX Timer Tick",
+	.handler	= iop3xx_timer_interrupt,
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+};
+
+void __init iop3xx_init_time(unsigned long tick_rate)
+{
+	u32 timer_ctl;
+
+	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
+	ticks_per_usec = tick_rate / 1000000;
+	next_jiffy_time = 0xffffffff;
+
+	timer_ctl = IOP3XX_TMR_EN | IOP3XX_TMR_PRIVILEGED |
+			IOP3XX_TMR_RELOAD | IOP3XX_TMR_RATIO_1_1;
+
+	/*
+	 * We use timer 0 for our timer interrupt, and timer 1 as
+	 * monotonic counter for tracking missed jiffies.
+	 */
+	iop3xx_cp6_enable();
+	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (ticks_per_jiffy - 1));
+	asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
+	asm volatile("mcr p6, 0, %0, c5, c1, 0" : : "r" (0xffffffff));
+	asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
+	iop3xx_cp6_disable();
+
+	setup_irq(IRQ_IOP3XX_TIMER0, &iop3xx_timer_irq);
+}
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 7f45c7c..f1179ad 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -100,6 +100,7 @@
 		return;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
+	BUG_ON(clk->usecount == 0);
 	if (arch_clock->clk_disable)
 		arch_clock->clk_disable(clk);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -322,6 +323,31 @@
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+/*
+ * Disable any unused clocks left on by the bootloader
+ */
+static int __init clk_disable_unused(void)
+{
+	struct clk *ck;
+	unsigned long flags;
+
+	list_for_each_entry(ck, &clocks, node) {
+		if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
+			ck->enable_reg == 0)
+			continue;
+
+		spin_lock_irqsave(&clockfw_lock, flags);
+		if (arch_clock->clk_disable_unused)
+			arch_clock->clk_disable_unused(ck);
+		spin_unlock_irqrestore(&clockfw_lock, flags);
+	}
+
+	return 0;
+}
+late_initcall(clk_disable_unused);
+#endif
+
 int __init clk_init(struct clk_functions * custom_clocks)
 {
 	if (!custom_clocks) {
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 1812f23..dbc3f44 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -148,7 +148,7 @@
 
 #ifdef CONFIG_ARCH_OMAP24XX
 #define	OMAP_MMC1_BASE		0x4809c000
-#define OMAP_MMC1_INT		83
+#define OMAP_MMC1_INT		INT_24XX_MMC_IRQ
 #else
 #define	OMAP_MMC1_BASE		0xfffb7800
 #define OMAP_MMC1_INT		INT_MMC
@@ -225,7 +225,14 @@
 	/* block 1 is always available and has just one pinout option */
 	mmc = &mmc_conf->mmc[0];
 	if (mmc->enabled) {
-		if (!cpu_is_omap24xx()) {
+		if (cpu_is_omap24xx()) {
+			omap_cfg_reg(H18_24XX_MMC_CMD);
+			omap_cfg_reg(H15_24XX_MMC_CLKI);
+			omap_cfg_reg(G19_24XX_MMC_CLKO);
+			omap_cfg_reg(F20_24XX_MMC_DAT0);
+			omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
+			omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
+		} else {
 			omap_cfg_reg(MMC_CMD);
 			omap_cfg_reg(MMC_CLK);
 			omap_cfg_reg(MMC_DAT0);
@@ -236,7 +243,14 @@
 			}
 		}
 		if (mmc->wire4) {
-			if (!cpu_is_omap24xx()) {
+			if (cpu_is_omap24xx()) {
+				omap_cfg_reg(H14_24XX_MMC_DAT1);
+				omap_cfg_reg(E19_24XX_MMC_DAT2);
+				omap_cfg_reg(D19_24XX_MMC_DAT3);
+				omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
+				omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
+				omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
+			} else {
 				omap_cfg_reg(MMC_DAT1);
 				/* NOTE:  DAT2 can be on W10 (here) or M15 */
 				if (!mmc->nomux)
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 9eddc95..1bbb431 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -119,32 +119,41 @@
 		omap_writew(0, lch_base + i);
 }
 
-void omap_set_dma_priority(int dst_port, int priority)
+void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
 	u32 l;
 
-	switch (dst_port) {
-	case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
-		reg = OMAP_TC_OCPT1_PRIOR;
-		break;
-	case OMAP_DMA_PORT_OCP_T2:	/* FFFECCD0 */
-		reg = OMAP_TC_OCPT2_PRIOR;
-		break;
-	case OMAP_DMA_PORT_EMIFF:	/* FFFECC08 */
-		reg = OMAP_TC_EMIFF_PRIOR;
-		break;
-	case OMAP_DMA_PORT_EMIFS:	/* FFFECC04 */
-		reg = OMAP_TC_EMIFS_PRIOR;
-		break;
-	default:
-		BUG();
-		return;
+	if (cpu_class_is_omap1()) {
+		switch (dst_port) {
+		case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
+			reg = OMAP_TC_OCPT1_PRIOR;
+			break;
+		case OMAP_DMA_PORT_OCP_T2:	/* FFFECCD0 */
+			reg = OMAP_TC_OCPT2_PRIOR;
+			break;
+		case OMAP_DMA_PORT_EMIFF:	/* FFFECC08 */
+			reg = OMAP_TC_EMIFF_PRIOR;
+			break;
+		case OMAP_DMA_PORT_EMIFS:	/* FFFECC04 */
+			reg = OMAP_TC_EMIFS_PRIOR;
+			break;
+		default:
+			BUG();
+			return;
+		}
+		l = omap_readl(reg);
+		l &= ~(0xf << 8);
+		l |= (priority & 0xf) << 8;
+		omap_writel(l, reg);
 	}
-	l = omap_readl(reg);
-	l &= ~(0xf << 8);
-	l |= (priority & 0xf) << 8;
-	omap_writel(l, reg);
+
+	if (cpu_is_omap24xx()) {
+		if (priority)
+			OMAP_DMA_CCR_REG(lch) |= (1 << 6);
+		else
+			OMAP_DMA_CCR_REG(lch) &= ~(1 << 6);
+	}
 }
 
 void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
@@ -234,6 +243,14 @@
 	OMAP1_DMA_LCH_CTRL_REG(lch) = w;
 }
 
+void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
+{
+	if (cpu_is_omap24xx()) {
+		OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16);
+		OMAP_DMA_CSDP_REG(lch) |= (mode << 16);
+	}
+}
+
 /* Note that src_port is only for omap1 */
 void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 			     unsigned long src_start,
@@ -698,6 +715,32 @@
 }
 
 /*
+ * Allows changing the DMA callback function or data. This may be needed if
+ * the driver shares a single DMA channel for multiple dma triggers.
+ */
+int omap_set_dma_callback(int lch,
+			  void (* callback)(int lch, u16 ch_status, void *data),
+			  void *data)
+{
+	unsigned long flags;
+
+	if (lch < 0)
+		return -ENODEV;
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	if (dma_chan[lch].dev_id == -1) {
+		printk(KERN_ERR "DMA callback for not set for free channel\n");
+		spin_unlock_irqrestore(&dma_chan_lock, flags);
+		return -EINVAL;
+	}
+	dma_chan[lch].callback = callback;
+	dma_chan[lch].data = data;
+	spin_unlock_irqrestore(&dma_chan_lock, flags);
+
+	return 0;
+}
+
+/*
  * Returns current physical source address for the given DMA channel.
  * If the channel is running the caller must disable interrupts prior calling
  * this function and process the returned value before re-enabling interrupt to
@@ -1339,6 +1382,14 @@
 			dma_chan_count = 16;
 		} else
 			dma_chan_count = 9;
+		if (cpu_is_omap16xx()) {
+			u16 w;
+
+			/* this would prevent OMAP sleep */
+			w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+			w &= ~(1 << 8);
+			omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+		}
 	} else if (cpu_is_omap24xx()) {
 		u8 revision = omap_readb(OMAP_DMA4_REVISION);
 		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
@@ -1414,11 +1465,13 @@
 EXPORT_SYMBOL(omap_free_dma);
 EXPORT_SYMBOL(omap_start_dma);
 EXPORT_SYMBOL(omap_stop_dma);
+EXPORT_SYMBOL(omap_set_dma_callback);
 EXPORT_SYMBOL(omap_enable_dma_irq);
 EXPORT_SYMBOL(omap_disable_dma_irq);
 
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 EXPORT_SYMBOL(omap_set_dma_color_mode);
+EXPORT_SYMBOL(omap_set_dma_write_mode);
 
 EXPORT_SYMBOL(omap_set_dma_src_params);
 EXPORT_SYMBOL(omap_set_dma_src_index);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 5052443..bcbb8d7 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -75,10 +75,14 @@
 #endif
 	void __iomem *io_base;
 	unsigned reserved:1;
+	unsigned enabled:1;
 };
 
 #ifdef CONFIG_ARCH_OMAP1
 
+#define omap_dm_clk_enable(x)
+#define omap_dm_clk_disable(x)
+
 static struct omap_dm_timer dm_timers[] = {
 	{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
 	{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
@@ -92,6 +96,9 @@
 
 #elif defined(CONFIG_ARCH_OMAP2)
 
+#define omap_dm_clk_enable(x) clk_enable(x)
+#define omap_dm_clk_disable(x) clk_disable(x)
+
 static struct omap_dm_timer dm_timers[] = {
 	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
 	{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
@@ -154,24 +161,28 @@
 {
 	u32 l;
 
-	if (timer != &dm_timers[0]) {
+	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
 		omap_dm_timer_wait_for_reset(timer);
 	}
-	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK);
+	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 
 	/* Set to smart-idle mode */
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
 	l |= 0x02 << 3;
+
+	if (cpu_class_is_omap2() && timer == &dm_timers[0]) {
+		/* Enable wake-up only for GPT1 on OMAP2 CPUs*/
+		l |= 1 << 2;
+		/* Non-posted mode */
+		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0);
+	}
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
 }
 
 static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-#ifdef CONFIG_ARCH_OMAP2
-	clk_enable(timer->iclk);
-	clk_enable(timer->fclk);
-#endif
+	omap_dm_timer_enable(timer);
 	omap_dm_timer_reset(timer);
 }
 
@@ -223,15 +234,36 @@
 
 void omap_dm_timer_free(struct omap_dm_timer *timer)
 {
+	omap_dm_timer_enable(timer);
 	omap_dm_timer_reset(timer);
-#ifdef CONFIG_ARCH_OMAP2
-	clk_disable(timer->iclk);
-	clk_disable(timer->fclk);
-#endif
+	omap_dm_timer_disable(timer);
+
 	WARN_ON(!timer->reserved);
 	timer->reserved = 0;
 }
 
+void omap_dm_timer_enable(struct omap_dm_timer *timer)
+{
+	if (timer->enabled)
+		return;
+
+	omap_dm_clk_enable(timer->fclk);
+	omap_dm_clk_enable(timer->iclk);
+
+	timer->enabled = 1;
+}
+
+void omap_dm_timer_disable(struct omap_dm_timer *timer)
+{
+	if (!timer->enabled)
+		return;
+
+	omap_dm_clk_disable(timer->iclk);
+	omap_dm_clk_disable(timer->fclk);
+
+	timer->enabled = 0;
+}
+
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
 	return timer->irq;
@@ -276,7 +308,7 @@
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-        return timer->fclk;
+	return timer->fclk;
 }
 
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
@@ -406,11 +438,16 @@
 				  unsigned int value)
 {
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
 }
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
-	return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+	unsigned int l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+
+	return l;
 }
 
 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
@@ -420,12 +457,16 @@
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-	return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+	unsigned int l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+
+	return l;
 }
 
 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
-	return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
 }
 
 int omap_dm_timers_active(void)
@@ -436,9 +477,14 @@
 		struct omap_dm_timer *timer;
 
 		timer = &dm_timers[i];
+
+		if (!timer->enabled)
+			continue;
+
 		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
-		    OMAP_TIMER_CTRL_ST)
+		    OMAP_TIMER_CTRL_ST) {
 			return 1;
+		}
 	}
 	return 0;
 }
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index cd7f973..f55f99a 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -94,6 +94,8 @@
 #define OMAP24XX_GPIO_SYSCONFIG		0x0010
 #define OMAP24XX_GPIO_SYSSTATUS		0x0014
 #define OMAP24XX_GPIO_IRQSTATUS1	0x0018
+#define OMAP24XX_GPIO_IRQSTATUS2	0x0028
+#define OMAP24XX_GPIO_IRQENABLE2	0x002c
 #define OMAP24XX_GPIO_IRQENABLE1	0x001c
 #define OMAP24XX_GPIO_CTRL		0x0030
 #define OMAP24XX_GPIO_OE		0x0034
@@ -110,8 +112,6 @@
 #define OMAP24XX_GPIO_CLEARDATAOUT	0x0090
 #define OMAP24XX_GPIO_SETDATAOUT	0x0094
 
-#define OMAP_MPUIO_MASK		(~OMAP_MAX_GPIO_LINES & 0xff)
-
 struct gpio_bank {
 	void __iomem *base;
 	u16 irq;
@@ -216,11 +216,13 @@
 {
 	if (gpio < 0)
 		return -1;
+#ifndef CONFIG_ARCH_OMAP24XX
 	if (OMAP_GPIO_IS_MPUIO(gpio)) {
-		if ((gpio & OMAP_MPUIO_MASK) > 16)
+		if (gpio >= OMAP_MAX_GPIO_LINES + 16)
 			return -1;
 		return 0;
 	}
+#endif
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap15xx() && gpio < 16)
 		return 0;
@@ -529,6 +531,10 @@
 		return;
 	}
 	__raw_writel(gpio_mask, reg);
+
+	/* Workaround for clearing DSP GPIO interrupts to allow retention */
+	if (cpu_is_omap2420())
+		__raw_writel(gpio_mask, bank->base + OMAP24XX_GPIO_IRQSTATUS2);
 }
 
 static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
@@ -662,6 +668,14 @@
 	}
 }
 
+static void _reset_gpio(struct gpio_bank *bank, int gpio)
+{
+	_set_gpio_direction(bank, get_gpio_index(gpio), 1);
+	_set_gpio_irqenable(bank, gpio, 0);
+	_clear_gpio_irqstatus(bank, gpio);
+	_set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
+}
+
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int gpio_wake_enable(unsigned int irq, unsigned int enable)
 {
@@ -672,9 +686,7 @@
 	if (check_gpio(gpio) < 0)
 		return -ENODEV;
 	bank = get_gpio_bank(gpio);
-	spin_lock(&bank->lock);
 	retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
-	spin_unlock(&bank->lock);
 
 	return retval;
 }
@@ -696,7 +708,9 @@
 	}
 	bank->reserved_map |= (1 << get_gpio_index(gpio));
 
-	/* Set trigger to none. You need to enable the trigger after request_irq */
+	/* Set trigger to none. You need to enable the desired trigger with
+	 * request_irq() or set_irq_type().
+	 */
 	_set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
 
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -756,9 +770,7 @@
 	}
 #endif
 	bank->reserved_map &= ~(1 << get_gpio_index(gpio));
-	_set_gpio_direction(bank, get_gpio_index(gpio), 1);
-	_set_gpio_irqenable(bank, gpio, 0);
-	_clear_gpio_irqstatus(bank, gpio);
+	_reset_gpio(bank, gpio);
 	spin_unlock(&bank->lock);
 }
 
@@ -898,6 +910,14 @@
 
 }
 
+static void gpio_irq_shutdown(unsigned int irq)
+{
+	unsigned int gpio = irq - IH_GPIO_BASE;
+	struct gpio_bank *bank = get_gpio_bank(gpio);
+
+	_reset_gpio(bank, gpio);
+}
+
 static void gpio_ack_irq(unsigned int irq)
 {
 	unsigned int gpio = irq - IH_GPIO_BASE;
@@ -946,6 +966,7 @@
 
 static struct irq_chip gpio_irq_chip = {
 	.name		= "GPIO",
+	.shutdown	= gpio_irq_shutdown,
 	.ack		= gpio_ack_irq,
 	.mask		= gpio_mask_irq,
 	.unmask		= gpio_unmask_irq,
@@ -985,7 +1006,7 @@
 		else
 			clk_enable(gpio_ick);
 		gpio_fck = clk_get(NULL, "gpios_fck");
-		if (IS_ERR(gpio_ick))
+		if (IS_ERR(gpio_fck))
 			printk("Could not get gpios_fck\n");
 		else
 			clk_enable(gpio_fck);
@@ -1144,8 +1165,8 @@
 			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
 			break;
 		case METHOD_GPIO_24XX:
-			wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
 			break;
 		default:
 			continue;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 196aac3..ade9a0f 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -75,8 +75,6 @@
 static struct clk *mcbsp1_fck = 0;
 static struct clk *mcbsp2_ick = 0;
 static struct clk *mcbsp2_fck = 0;
-static struct clk *sys_ck = 0;
-static struct clk *sys_clkout = 0;
 #endif
 
 static void omap_mcbsp_dump_reg(u8 id)
@@ -232,7 +230,6 @@
 	omap_cfg_reg(W15_24XX_MCBSP2_DR);
 	omap_cfg_reg(V15_24XX_MCBSP2_DX);
 	omap_cfg_reg(V14_24XX_GPIO117);
-	omap_cfg_reg(W14_24XX_SYS_CLKOUT);
 }
 #endif
 
@@ -984,13 +981,7 @@
 	if (cpu_is_omap24xx()) {
 		mcbsp_info = mcbsp_24xx;
 		mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
-
-		/* REVISIT: where's the right place? */
 		omap2_mcbsp2_mux_setup();
-		sys_ck = clk_get(0, "sys_ck");
-		sys_clkout = clk_get(0, "sys_clkout");
-		clk_set_parent(sys_clkout, sys_ck);
-		clk_enable(sys_clkout);
 	}
 #endif
 	for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
deleted file mode 100644
index 04b4102..0000000
--- a/arch/arm/plat-omap/pm.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/pm.c
- *
- * OMAP Power Management Routines
- *
- * Original code for the SA11x0:
- * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
- *
- * Modified for the PXA250 by Nicolas Pitre:
- * Copyright (c) 2002 Monta Vista Software, Inc.
- *
- * Modified for the OMAP1510 by David Singleton:
- * Copyright (c) 2002 Monta Vista Software, Inc.
- *
- * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.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/pm.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/pm.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-
-#include <asm/mach-types.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/tc.h>
-#include <asm/arch/pm.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/tps65010.h>
-#include <asm/arch/dsp_common.h>
-
-#include <asm/arch/clock.h>
-#include <asm/arch/sram.h>
-
-static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
-static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
-static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
-static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
-static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
-
-static void (*omap_sram_idle)(void) = NULL;
-static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
-
-/*
- * Let's power down on idle, but only if we are really
- * idle, because once we start down the path of
- * going idle we continue to do idle even if we get
- * a clock tick interrupt . .
- */
-void omap_pm_idle(void)
-{
-	unsigned int mask32 = 0;
-
-	/*
-	 * If the DSP is being used let's just idle the CPU, the overhead
-	 * to wake up from Big Sleep is big, milliseconds versus micro
-	 * seconds for wait for interrupt.
-	 */
-
-	local_irq_disable();
-	local_fiq_disable();
-	if (need_resched()) {
-		local_fiq_enable();
-		local_irq_enable();
-		return;
-	}
-	mask32 = omap_readl(ARM_SYSST);
-
-	/*
-	 * Prevent the ULPD from entering low power state by setting
-	 * POWER_CTRL_REG:4 = 0
-	 */
-	omap_writew(omap_readw(ULPD_POWER_CTRL) &
-		    ~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL);
-
-	/*
-	 * Since an interrupt may set up a timer, we don't want to
-	 * reprogram the hardware timer with interrupts enabled.
-	 * Re-enable interrupts only after returning from idle.
-	 */
-	timer_dyn_reprogram();
-
-	if ((mask32 & DSP_IDLE) == 0) {
-		__asm__ volatile ("mcr	p15, 0, r0, c7, c0, 4");
-	} else
-		omap_sram_idle();
-
-	local_fiq_enable();
-	local_irq_enable();
-}
-
-/*
- * Configuration of the wakeup event is board specific. For the
- * moment we put it into this helper function. Later it may move
- * to board specific files.
- */
-static void omap_pm_wakeup_setup(void)
-{
-	u32 level1_wake = 0;
-	u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
-
-	/*
-	 * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
-	 * and the L2 wakeup interrupts: keypad and UART2. Note that the
-	 * drivers must still separately call omap_set_gpio_wakeup() to
-	 * wake up to a GPIO interrupt.
-	 */
-	if (cpu_is_omap730())
-		level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
-			OMAP_IRQ_BIT(INT_730_IH2_IRQ);
-	else if (cpu_is_omap1510())
-		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
-			OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
-	else if (cpu_is_omap16xx())
-		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
-			OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
-
-	omap_writel(~level1_wake, OMAP_IH1_MIR);
-
-	if (cpu_is_omap730()) {
-		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
-		omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) | OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)), OMAP_IH2_1_MIR);
-	} else if (cpu_is_omap1510()) {
-		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
-		omap_writel(~level2_wake,  OMAP_IH2_MIR);
-	} else if (cpu_is_omap16xx()) {
-		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
-		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
-
-		/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
-		omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR);
-		omap_writel(~0x0, OMAP_IH2_2_MIR);
-		omap_writel(~0x0, OMAP_IH2_3_MIR);
-	}
-
-	/*  New IRQ agreement, recalculate in cascade order */
-	omap_writel(1, OMAP_IH2_CONTROL);
- 	omap_writel(1, OMAP_IH1_CONTROL);
-}
-
-void omap_pm_suspend(void)
-{
-	unsigned long arg0 = 0, arg1 = 0;
-
-	printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
-
-	omap_serial_wake_trigger(1);
-
-	if (machine_is_omap_osk()) {
-		/* Stop LED1 (D9) blink */
-		tps65010_set_led(LED1, OFF);
-	}
-
-	omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
-
-	/*
-	 * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
-	 */
-
-	local_irq_disable();
-	local_fiq_disable();
-
-	/*
-	 * Step 2: save registers
-	 *
-	 * The omap is a strange/beautiful device. The caches, memory
-	 * and register state are preserved across power saves.
-	 * We have to save and restore very little register state to
-	 * idle the omap.
-         *
- 	 * Save interrupt, MPUI, ARM and UPLD control registers.
-	 */
-
-	if (cpu_is_omap730()) {
-		MPUI730_SAVE(OMAP_IH1_MIR);
-		MPUI730_SAVE(OMAP_IH2_0_MIR);
-		MPUI730_SAVE(OMAP_IH2_1_MIR);
-		MPUI730_SAVE(MPUI_CTRL);
-		MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
-		MPUI730_SAVE(MPUI_DSP_API_CONFIG);
-		MPUI730_SAVE(EMIFS_CONFIG);
-		MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
-
-	} else if (cpu_is_omap1510()) {
-		MPUI1510_SAVE(OMAP_IH1_MIR);
-		MPUI1510_SAVE(OMAP_IH2_MIR);
-		MPUI1510_SAVE(MPUI_CTRL);
-		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
-		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
-		MPUI1510_SAVE(EMIFS_CONFIG);
-		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
-	} else if (cpu_is_omap16xx()) {
-		MPUI1610_SAVE(OMAP_IH1_MIR);
-		MPUI1610_SAVE(OMAP_IH2_0_MIR);
-		MPUI1610_SAVE(OMAP_IH2_1_MIR);
-		MPUI1610_SAVE(OMAP_IH2_2_MIR);
-		MPUI1610_SAVE(OMAP_IH2_3_MIR);
-		MPUI1610_SAVE(MPUI_CTRL);
-		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
-		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
-		MPUI1610_SAVE(EMIFS_CONFIG);
-		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
-	}
-
-	ARM_SAVE(ARM_CKCTL);
-	ARM_SAVE(ARM_IDLECT1);
-	ARM_SAVE(ARM_IDLECT2);
-	if (!(cpu_is_omap1510()))
-		ARM_SAVE(ARM_IDLECT3);
-	ARM_SAVE(ARM_EWUPCT);
-	ARM_SAVE(ARM_RSTCT1);
-	ARM_SAVE(ARM_RSTCT2);
-	ARM_SAVE(ARM_SYSST);
-	ULPD_SAVE(ULPD_CLOCK_CTRL);
-	ULPD_SAVE(ULPD_STATUS_REQ);
-
-	/* (Step 3 removed - we now allow deep sleep by default) */
-
-	/*
-	 * Step 4: OMAP DSP Shutdown
-	 */
-
-
-	/*
-	 * Step 5: Wakeup Event Setup
-	 */
-
-	omap_pm_wakeup_setup();
-
-	/*
-	 * Step 6: ARM and Traffic controller shutdown
-	 */
-
-	/* disable ARM watchdog */
-	omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
-	omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
-
-	/*
-	 * Step 6b: ARM and Traffic controller shutdown
-	 *
-	 * Step 6 continues here. Prepare jump to power management
-	 * assembly code in internal SRAM.
-	 *
-	 * Since the omap_cpu_suspend routine has been copied to
-	 * SRAM, we'll do an indirect procedure call to it and pass the
-	 * contents of arm_idlect1 and arm_idlect2 so it can restore
-	 * them when it wakes up and it will return.
-	 */
-
-	arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
-	arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
-
-	/*
-	 * Step 6c: ARM and Traffic controller shutdown
-	 *
-	 * Jump to assembly code. The processor will stay there
- 	 * until wake up.
-	 */
-        omap_sram_suspend(arg0, arg1);
-
-	/*
-	 * If we are here, processor is woken up!
-	 */
-
-	/*
-	 * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
-	 */
-
-	if (!(cpu_is_omap1510()))
-		ARM_RESTORE(ARM_IDLECT3);
-	ARM_RESTORE(ARM_CKCTL);
-	ARM_RESTORE(ARM_EWUPCT);
-	ARM_RESTORE(ARM_RSTCT1);
-	ARM_RESTORE(ARM_RSTCT2);
-	ARM_RESTORE(ARM_SYSST);
-	ULPD_RESTORE(ULPD_CLOCK_CTRL);
-	ULPD_RESTORE(ULPD_STATUS_REQ);
-
-	if (cpu_is_omap730()) {
-		MPUI730_RESTORE(EMIFS_CONFIG);
-		MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
-		MPUI730_RESTORE(OMAP_IH1_MIR);
-		MPUI730_RESTORE(OMAP_IH2_0_MIR);
-		MPUI730_RESTORE(OMAP_IH2_1_MIR);
-	} else if (cpu_is_omap1510()) {
-		MPUI1510_RESTORE(MPUI_CTRL);
-		MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
-		MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
-		MPUI1510_RESTORE(EMIFS_CONFIG);
-		MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
-		MPUI1510_RESTORE(OMAP_IH1_MIR);
-		MPUI1510_RESTORE(OMAP_IH2_MIR);
-	} else if (cpu_is_omap16xx()) {
-		MPUI1610_RESTORE(MPUI_CTRL);
-		MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
-		MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
-		MPUI1610_RESTORE(EMIFS_CONFIG);
-		MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
-
-		MPUI1610_RESTORE(OMAP_IH1_MIR);
-		MPUI1610_RESTORE(OMAP_IH2_0_MIR);
-		MPUI1610_RESTORE(OMAP_IH2_1_MIR);
-		MPUI1610_RESTORE(OMAP_IH2_2_MIR);
-		MPUI1610_RESTORE(OMAP_IH2_3_MIR);
-	}
-
-	omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
-
-	/*
-	 * Reenable interrupts
-	 */
-
-	local_irq_enable();
-	local_fiq_enable();
-
-	omap_serial_wake_trigger(0);
-
-	printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
-
-	if (machine_is_omap_osk()) {
-		/* Let LED1 (D9) blink again */
-		tps65010_set_led(LED1, BLINK);
-	}
-}
-
-#if defined(DEBUG) && defined(CONFIG_PROC_FS)
-static int g_read_completed;
-
-/*
- * Read system PM registers for debugging
- */
-static int omap_pm_read_proc(
-	char *page_buffer,
-	char **my_first_byte,
-	off_t virtual_start,
-	int length,
-	int *eof,
-	void *data)
-{
-	int my_buffer_offset = 0;
-	char * const my_base = page_buffer;
-
-	ARM_SAVE(ARM_CKCTL);
-	ARM_SAVE(ARM_IDLECT1);
-	ARM_SAVE(ARM_IDLECT2);
-	if (!(cpu_is_omap1510()))
-		ARM_SAVE(ARM_IDLECT3);
-	ARM_SAVE(ARM_EWUPCT);
-	ARM_SAVE(ARM_RSTCT1);
-	ARM_SAVE(ARM_RSTCT2);
-	ARM_SAVE(ARM_SYSST);
-
-	ULPD_SAVE(ULPD_IT_STATUS);
-	ULPD_SAVE(ULPD_CLOCK_CTRL);
-	ULPD_SAVE(ULPD_SOFT_REQ);
-	ULPD_SAVE(ULPD_STATUS_REQ);
-	ULPD_SAVE(ULPD_DPLL_CTRL);
-	ULPD_SAVE(ULPD_POWER_CTRL);
-
-	if (cpu_is_omap730()) {
-		MPUI730_SAVE(MPUI_CTRL);
-		MPUI730_SAVE(MPUI_DSP_STATUS);
-		MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
-		MPUI730_SAVE(MPUI_DSP_API_CONFIG);
-		MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
-		MPUI730_SAVE(EMIFS_CONFIG);
-	} else if (cpu_is_omap1510()) {
-		MPUI1510_SAVE(MPUI_CTRL);
-		MPUI1510_SAVE(MPUI_DSP_STATUS);
-		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
-		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
-		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
-		MPUI1510_SAVE(EMIFS_CONFIG);
-	} else if (cpu_is_omap16xx()) {
-		MPUI1610_SAVE(MPUI_CTRL);
-		MPUI1610_SAVE(MPUI_DSP_STATUS);
-		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
-		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
-		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
-		MPUI1610_SAVE(EMIFS_CONFIG);
-	}
-
-	if (virtual_start == 0) {
-		g_read_completed = 0;
-
-		my_buffer_offset += sprintf(my_base + my_buffer_offset,
-		   "ARM_CKCTL_REG:            0x%-8x     \n"
-		   "ARM_IDLECT1_REG:          0x%-8x     \n"
-		   "ARM_IDLECT2_REG:          0x%-8x     \n"
-		   "ARM_IDLECT3_REG:	      0x%-8x     \n"
-		   "ARM_EWUPCT_REG:           0x%-8x     \n"
-		   "ARM_RSTCT1_REG:           0x%-8x     \n"
-		   "ARM_RSTCT2_REG:           0x%-8x     \n"
-		   "ARM_SYSST_REG:            0x%-8x     \n"
-		   "ULPD_IT_STATUS_REG:       0x%-4x     \n"
-		   "ULPD_CLOCK_CTRL_REG:      0x%-4x     \n"
-		   "ULPD_SOFT_REQ_REG:        0x%-4x     \n"
-		   "ULPD_DPLL_CTRL_REG:       0x%-4x     \n"
-		   "ULPD_STATUS_REQ_REG:      0x%-4x     \n"
-		   "ULPD_POWER_CTRL_REG:      0x%-4x     \n",
-		   ARM_SHOW(ARM_CKCTL),
-		   ARM_SHOW(ARM_IDLECT1),
-		   ARM_SHOW(ARM_IDLECT2),
-		   ARM_SHOW(ARM_IDLECT3),
-		   ARM_SHOW(ARM_EWUPCT),
-		   ARM_SHOW(ARM_RSTCT1),
-		   ARM_SHOW(ARM_RSTCT2),
-		   ARM_SHOW(ARM_SYSST),
-		   ULPD_SHOW(ULPD_IT_STATUS),
-		   ULPD_SHOW(ULPD_CLOCK_CTRL),
-		   ULPD_SHOW(ULPD_SOFT_REQ),
-		   ULPD_SHOW(ULPD_DPLL_CTRL),
-		   ULPD_SHOW(ULPD_STATUS_REQ),
-		   ULPD_SHOW(ULPD_POWER_CTRL));
-
-		if (cpu_is_omap730()) {
-			my_buffer_offset += sprintf(my_base + my_buffer_offset,
-			   "MPUI730_CTRL_REG	     0x%-8x \n"
-			   "MPUI730_DSP_STATUS_REG:      0x%-8x \n"
-			   "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
-	 "MPUI730_DSP_API_CONFIG_REG:  0x%-8x \n"
-	 "MPUI730_SDRAM_CONFIG_REG:    0x%-8x \n"
-	 "MPUI730_EMIFS_CONFIG_REG:    0x%-8x \n",
-	 MPUI730_SHOW(MPUI_CTRL),
-	 MPUI730_SHOW(MPUI_DSP_STATUS),
-	 MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
-	 MPUI730_SHOW(MPUI_DSP_API_CONFIG),
-	 MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
-	 MPUI730_SHOW(EMIFS_CONFIG));
-		} else if (cpu_is_omap1510()) {
-			my_buffer_offset += sprintf(my_base + my_buffer_offset,
-			   "MPUI1510_CTRL_REG             0x%-8x \n"
-			   "MPUI1510_DSP_STATUS_REG:      0x%-8x \n"
-			   "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
-		   	   "MPUI1510_DSP_API_CONFIG_REG:  0x%-8x \n"
-		   	   "MPUI1510_SDRAM_CONFIG_REG:    0x%-8x \n"
-		   	   "MPUI1510_EMIFS_CONFIG_REG:    0x%-8x \n",
-		   	   MPUI1510_SHOW(MPUI_CTRL),
-		   	   MPUI1510_SHOW(MPUI_DSP_STATUS),
-		   	   MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
-		   	   MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
-		   	   MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
-		   	   MPUI1510_SHOW(EMIFS_CONFIG));
-		} else if (cpu_is_omap16xx()) {
-			my_buffer_offset += sprintf(my_base + my_buffer_offset,
-			   "MPUI1610_CTRL_REG             0x%-8x \n"
-			   "MPUI1610_DSP_STATUS_REG:      0x%-8x \n"
-			   "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
-		   	   "MPUI1610_DSP_API_CONFIG_REG:  0x%-8x \n"
-		   	   "MPUI1610_SDRAM_CONFIG_REG:    0x%-8x \n"
-		   	   "MPUI1610_EMIFS_CONFIG_REG:    0x%-8x \n",
-		   	   MPUI1610_SHOW(MPUI_CTRL),
-		   	   MPUI1610_SHOW(MPUI_DSP_STATUS),
-		   	   MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
-		   	   MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
-		   	   MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
-		   	   MPUI1610_SHOW(EMIFS_CONFIG));
-		}
-
-		g_read_completed++;
-	} else if (g_read_completed >= 1) {
-		 *eof = 1;
-		 return 0;
-	}
-	g_read_completed++;
-
-	*my_first_byte = page_buffer;
-	return  my_buffer_offset;
-}
-
-static void omap_pm_init_proc(void)
-{
-	struct proc_dir_entry *entry;
-
-	entry = create_proc_read_entry("driver/omap_pm",
-				       S_IWUSR | S_IRUGO, NULL,
-	   omap_pm_read_proc, NULL);
-}
-
-#endif /* DEBUG && CONFIG_PROC_FS */
-
-/*
- *	omap_pm_prepare - Do preliminary suspend work.
- *	@state:		suspend state we're entering.
- *
- */
-//#include <asm/hardware.h>
-
-static int omap_pm_prepare(suspend_state_t state)
-{
-	int error = 0;
-
-	switch (state)
-	{
-	case PM_SUSPEND_STANDBY:
-	case PM_SUSPEND_MEM:
-		break;
-
-	case PM_SUSPEND_DISK:
-		return -ENOTSUPP;
-
-	default:
-		return -EINVAL;
-	}
-
-	return error;
-}
-
-
-/*
- *	omap_pm_enter - Actually enter a sleep state.
- *	@state:		State we're entering.
- *
- */
-
-static int omap_pm_enter(suspend_state_t state)
-{
-	switch (state)
-	{
-	case PM_SUSPEND_STANDBY:
-	case PM_SUSPEND_MEM:
-		omap_pm_suspend();
-		break;
-
-	case PM_SUSPEND_DISK:
-		return -ENOTSUPP;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
-/**
- *	omap_pm_finish - Finish up suspend sequence.
- *	@state:		State we're coming out of.
- *
- *	This is called after we wake back up (or if entering the sleep state
- *	failed).
- */
-
-static int omap_pm_finish(suspend_state_t state)
-{
-	return 0;
-}
-
-
-static irqreturn_t  omap_wakeup_interrupt(int  irq, void *  dev,
-				     struct pt_regs *  regs)
-{
-	return IRQ_HANDLED;
-}
-
-static struct irqaction omap_wakeup_irq = {
-	.name		= "peripheral wakeup",
-	.flags		= IRQF_DISABLED,
-	.handler	= omap_wakeup_interrupt
-};
-
-
-
-static struct pm_ops omap_pm_ops ={
-	.pm_disk_mode = 0,
-        .prepare        = omap_pm_prepare,
-        .enter          = omap_pm_enter,
-        .finish         = omap_pm_finish,
-};
-
-static int __init omap_pm_init(void)
-{
-	printk("Power Management for TI OMAP.\n");
-	/*
-	 * We copy the assembler sleep/wakeup routines to SRAM.
-	 * These routines need to be in SRAM as that's the only
-	 * memory the MPU can see when it wakes up.
-	 */
-	if (cpu_is_omap730()) {
-		omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
-						omap730_idle_loop_suspend_sz);
-		omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
-	 omap730_cpu_suspend_sz);
-	} else if (cpu_is_omap1510()) {
-		omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
-						omap1510_idle_loop_suspend_sz);
-		omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
-						   omap1510_cpu_suspend_sz);
-	} else if (cpu_is_omap16xx()) {
-		omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
-						omap1610_idle_loop_suspend_sz);
-		omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
-						   omap1610_cpu_suspend_sz);
-	}
-
-	if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
-		printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
-		return -ENODEV;
-	}
-
-	pm_idle = omap_pm_idle;
-
-	if (cpu_is_omap730())
-		setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
-	else if (cpu_is_omap16xx())
-		setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
-
-#if 0
-	/* --- BEGIN BOARD-DEPENDENT CODE --- */
-	/* Sleepx mask direction */
-	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
-	/* Unmask sleepx signal */
-	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
-	/* --- END BOARD-DEPENDENT CODE --- */
-#endif
-
-	/* Program new power ramp-up time
-	 * (0 for most boards since we don't lower voltage when in deep sleep)
-	 */
-	omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
-
-	/* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
-	omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
-
-	/* Configure IDLECT3 */
-	if (cpu_is_omap730())
-		omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
-	else if (cpu_is_omap16xx())
-		omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
-
-	pm_set_ops(&omap_pm_ops);
-
-#if defined(DEBUG) && defined(CONFIG_PROC_FS)
-	omap_pm_init_proc();
-#endif
-
-	if (cpu_is_omap16xx()) {
-		/* configure LOW_PWR pin */
-		omap_cfg_reg(T20_1610_LOW_PWR);
-	}
-
-	return 0;
-}
-__initcall(omap_pm_init);
-
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index e757183..19014b2 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -174,10 +174,7 @@
 	if (cpu_is_omap24xx()) {
 		omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
 
-		if (is_sram_locked())
-			base = OMAP2_SRAM_PUB_PA;
-		else
-			base = OMAP2_SRAM_PA;
+		base = OMAP2_SRAM_PA;
 		base = ROUND_DOWN(base, PAGE_SIZE);
 		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
 	}
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
index 281ecc7..cf6df33 100644
--- a/arch/arm/plat-omap/timer32k.c
+++ b/arch/arm/plat-omap/timer32k.c
@@ -105,6 +105,8 @@
 
 static inline void omap_32k_timer_start(unsigned long load_val)
 {
+	if (!load_val)
+		load_val = 1;
 	omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
 	omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
 }
@@ -192,14 +194,11 @@
  * issues with dynamic tick. In the dynamic tick case, we need to lock
  * with irqsave.
  */
-static 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,
+					struct pt_regs *regs)
 {
-	unsigned long flags;
 	unsigned long now;
 
-	write_seqlock_irqsave(&xtime_lock, flags);
-
 	omap_32k_timer_ack_irq();
 	now = omap_32k_sync_timer_read();
 
@@ -215,6 +214,23 @@
 	 * continuous timer can be overridden from pm_idle to be longer.
 	 */
 	omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id,
+					struct pt_regs *regs)
+{
+	return _omap_32k_timer_interrupt(irq, dev_id, regs);
+}
+
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+					    struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+	_omap_32k_timer_interrupt(irq, dev_id, regs);
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 
 	return IRQ_HANDLED;
@@ -230,7 +246,15 @@
  */
 void omap_32k_timer_reprogram(unsigned long next_tick)
 {
-	omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+	unsigned long ticks = JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1;
+	unsigned long now = omap_32k_sync_timer_read();
+	unsigned long idled = now - omap_32k_last_tick;
+
+	if (idled + 1 < ticks)
+		ticks -= idled;
+	else
+		ticks = 1;
+	omap_32k_timer_start(ticks);
 }
 
 static struct irqaction omap_32k_timer_irq;
@@ -252,7 +276,7 @@
 	.enable		= omap_32k_timer_enable_dyn_tick,
 	.disable	= omap_32k_timer_disable_dyn_tick,
 	.reprogram	= omap_32k_timer_reprogram,
-	.handler	= omap_32k_timer_interrupt,
+	.handler	= omap_32k_timer_handler,
 };
 #endif	/* CONFIG_NO_IDLE_HZ */
 
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index 9b81532..7e80968 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -26,7 +26,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index e1372a2..b02af1d 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon Jun 26 22:26:08 2006
+# Last update: Sat Sep 23 13:20:43 2006
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -329,7 +329,7 @@
 nimbra210		ARCH_NIMBRA210		NIMBRA210		312
 hhp_d95xx		ARCH_HHP_D95XX		HHP_D95XX		313
 labarm			ARCH_LABARM		LABARM			314
-comcerto		ARCH_M825XX		M825XX			315
+m825xx			ARCH_M825XX		M825XX			315
 m7100			SA1100_M7100		M7100			316
 nipc2			ARCH_NIPC2		NIPC2			317
 fu7202			ARCH_FU7202		FU7202			318
@@ -857,12 +857,12 @@
 maestro			MACH_MAESTRO		MAESTRO			843
 tunge2			MACH_TUNGE2		TUNGE2			844
 ixbbm			MACH_IXBBM		IXBBM			845
-mx27ads			MACH_MX27		MX27			846
+mx27ads			MACH_MX27ADS		MX27ADS			846
 ax8004			MACH_AX8004		AX8004			847
 at91sam9261ek		MACH_AT91SAM9261EK	AT91SAM9261EK		848
 loft			MACH_LOFT		LOFT			849
 magpie			MACH_MAGPIE		MAGPIE			850
-mx21ads			MACH_MX21		MX21			851
+mx21ads			MACH_MX21ADS		MX21ADS			851
 mb87m3400		MACH_MB87M3400		MB87M3400		852
 mguard_delta		MACH_MGUARD_DELTA	MGUARD_DELTA		853
 davinci_dvdp		MACH_DAVINCI_DVDP	DAVINCI_DVDP		854
@@ -1058,7 +1058,7 @@
 fontaine		MACH_FONTAINE		FONTAINE		1045
 wombat			MACH_WOMBAT		WOMBAT			1046
 acq300			MACH_ACQ300		ACQ300			1047
-mod_270			MACH_MOD_270		MOD_270			1048
+mod272			MACH_MOD_270		MOD_270			1048
 vmc_vc0820		MACH_VC0820		VC0820			1049
 ani_aim			MACH_ANI_AIM		ANI_AIM			1050
 jellyfish		MACH_JELLYFISH		JELLYFISH		1051
@@ -1093,3 +1093,67 @@
 eti_b1			MACH_ETI_B1		ETI_B1			1080
 za9l_series		MACH_ZILOG_ZA9L		ZILOG_ZA9L		1081
 bit2440			MACH_BIT2440		BIT2440			1082
+nbi			MACH_NBI		NBI			1083
+smdk2443		MACH_SMDK2443		SMDK2443		1084
+vdavinci		MACH_VDAVINCI		VDAVINCI		1085
+atc6			MACH_ATC6		ATC6			1086
+multmdw			MACH_MULTMDW		MULTMDW			1087
+mba2440			MACH_MBA2440		MBA2440			1088
+ecsd			MACH_ECSD		ECSD			1089
+zire31			MACH_ZIRE31		ZIRE31			1090
+fsg			MACH_FSG		FSG			1091
+razor101		MACH_RAZOR101		RAZOR101		1092
+opera_tdm		MACH_OPERA_TDM		OPERA_TDM		1093
+comcerto		MACH_COMCERTO		COMCERTO		1094
+tb0319			MACH_TB0319		TB0319			1095
+kws8000			MACH_KWS8000		KWS8000			1096
+b2			MACH_B2			B2			1097
+lcl54			MACH_LCL54		LCL54			1098
+at91sam9260ek		MACH_AT91SAM9260EK	AT91SAM9260EK		1099
+glantank		MACH_GLANTANK		GLANTANK		1100
+n2100			MACH_N2100		N2100			1101
+n4100			MACH_N4100		N4100			1102
+rsc4			MACH_VERTICAL_RSC4	VERTICAL_RSC4		1103
+sg8100			MACH_SG8100		SG8100			1104
+im42xx			MACH_IM42XX		IM42XX			1105
+ftxx			MACH_FTXX		FTXX			1106
+lwfusion		MACH_LWFUSION		LWFUSION		1107
+qt2410			MACH_QT2410		QT2410			1108
+kixrp435		MACH_KIXRP435		KIXRP435		1109
+ccw9c			MACH_CCW9C		CCW9C			1110
+dabhs			MACH_DABHS		DABHS			1111
+gzmx			MACH_GZMX		GZMX			1112
+ipnw100ap		MACH_IPNW100AP		IPNW100AP		1113
+cc9p9360dev		MACH_CC9P9360DEV	CC9P9360DEV		1114
+cc9p9750dev		MACH_CC9P9750DEV	CC9P9750DEV		1115
+cc9p9360val		MACH_CC9P9360VAL	CC9P9360VAL		1116
+cc9p9750val		MACH_CC9P9750VAL	CC9P9750VAL		1117
+nx70v			MACH_NX70V		NX70V			1118
+at91rm9200df		MACH_AT91RM9200DF	AT91RM9200DF		1119
+se_pilot2		MACH_SE_PILOT2		SE_PILOT2		1120
+mtcn_t800		MACH_MTCN_T800		MTCN_T800		1121
+vcmx212			MACH_VCMX212		VCMX212			1122
+lynx			MACH_LYNX		LYNX			1123
+at91sam9260id		MACH_AT91SAM9260ID	AT91SAM9260ID		1124
+hw86052			MACH_HW86052		HW86052			1125
+pilz_pmi3		MACH_PILZ_PMI3		PILZ_PMI3		1126
+edb9302a		MACH_EDB9302A		EDB9302A		1127
+edb9307a		MACH_EDB9307A		EDB9307A		1128
+ct_dfs			MACH_CT_DFS		CT_DFS			1129
+pilz_pmi4		MACH_PILZ_PMI4		PILZ_PMI4		1130
+xceednp_ixp		MACH_XCEEDNP_IXP	XCEEDNP_IXP		1131
+smdk2442b		MACH_SMDK2442B		SMDK2442B		1132
+xnode			MACH_XNODE		XNODE			1133
+aidx270			MACH_AIDX270		AIDX270			1134
+rema			MACH_REMA		REMA			1135
+bps1000			MACH_BPS1000		BPS1000			1136
+hw90350			MACH_HW90350		HW90350			1137
+omap_sdp3430		MACH_OMAP_SDP3430	OMAP_SDP3430		1138
+bluetouch		MACH_BLUETOUCH		BLUETOUCH		1139
+vstms			MACH_VSTMS		VSTMS			1140
+xsbase270		MACH_XSBASE270		XSBASE270		1141
+at91sam9260ek_cn	MACH_AT91SAM9260EK_CN	AT91SAM9260EK_CN	1142
+adsturboxb		MACH_ADSTURBOXB		ADSTURBOXB		1143
+oti4110			MACH_OTI4110		OTI4110			1144
+hme_pxa			MACH_HME_PXA		HME_PXA			1145
+deisterdca		MACH_DEISTERDCA		DEISTERDCA		1146
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index 96fdf30..f279789 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -355,3 +355,18 @@
  * we check for an error.
  */
 #define VFP_EXCEPTION_ERROR	((u32)-1 & ~VFP_NAN_FLAG)
+
+/*
+ * A flag to tell vfp instruction type.
+ *  OP_SCALAR - this operation always operates in scalar mode
+ *  OP_SD - the instruction exceptionally writes to a single precision result.
+ *  OP_DD - the instruction exceptionally writes to a double precision result.
+ */
+#define OP_SCALAR	(1 << 0)
+#define OP_SD		(1 << 1)
+#define OP_DD		(1 << 1)
+
+struct op {
+	u32 (* const fn)(int dd, int dn, int dm, u32 fpscr);
+	u32 flags;
+};
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index add48e3..4fc05ee 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -659,22 +659,22 @@
 }
 
 
-static u32 (* const fop_extfns[32])(int dd, int unused, int dm, u32 fpscr) = {
-	[FEXT_TO_IDX(FEXT_FCPY)]	= vfp_double_fcpy,
-	[FEXT_TO_IDX(FEXT_FABS)]	= vfp_double_fabs,
-	[FEXT_TO_IDX(FEXT_FNEG)]	= vfp_double_fneg,
-	[FEXT_TO_IDX(FEXT_FSQRT)]	= vfp_double_fsqrt,
-	[FEXT_TO_IDX(FEXT_FCMP)]	= vfp_double_fcmp,
-	[FEXT_TO_IDX(FEXT_FCMPE)]	= vfp_double_fcmpe,
-	[FEXT_TO_IDX(FEXT_FCMPZ)]	= vfp_double_fcmpz,
-	[FEXT_TO_IDX(FEXT_FCMPEZ)]	= vfp_double_fcmpez,
-	[FEXT_TO_IDX(FEXT_FCVT)]	= vfp_double_fcvts,
-	[FEXT_TO_IDX(FEXT_FUITO)]	= vfp_double_fuito,
-	[FEXT_TO_IDX(FEXT_FSITO)]	= vfp_double_fsito,
-	[FEXT_TO_IDX(FEXT_FTOUI)]	= vfp_double_ftoui,
-	[FEXT_TO_IDX(FEXT_FTOUIZ)]	= vfp_double_ftouiz,
-	[FEXT_TO_IDX(FEXT_FTOSI)]	= vfp_double_ftosi,
-	[FEXT_TO_IDX(FEXT_FTOSIZ)]	= vfp_double_ftosiz,
+static struct op fops_ext[32] = {
+	[FEXT_TO_IDX(FEXT_FCPY)]	= { vfp_double_fcpy,   0 },
+	[FEXT_TO_IDX(FEXT_FABS)]	= { vfp_double_fabs,   0 },
+	[FEXT_TO_IDX(FEXT_FNEG)]	= { vfp_double_fneg,   0 },
+	[FEXT_TO_IDX(FEXT_FSQRT)]	= { vfp_double_fsqrt,  0 },
+	[FEXT_TO_IDX(FEXT_FCMP)]	= { vfp_double_fcmp,   OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCMPE)]	= { vfp_double_fcmpe,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCMPZ)]	= { vfp_double_fcmpz,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCMPEZ)]	= { vfp_double_fcmpez, OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCVT)]	= { vfp_double_fcvts,  OP_SCALAR|OP_SD },
+	[FEXT_TO_IDX(FEXT_FUITO)]	= { vfp_double_fuito,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FSITO)]	= { vfp_double_fsito,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FTOUI)]	= { vfp_double_ftoui,  OP_SCALAR|OP_SD },
+	[FEXT_TO_IDX(FEXT_FTOUIZ)]	= { vfp_double_ftouiz, OP_SCALAR|OP_SD },
+	[FEXT_TO_IDX(FEXT_FTOSI)]	= { vfp_double_ftosi,  OP_SCALAR|OP_SD },
+	[FEXT_TO_IDX(FEXT_FTOSIZ)]	= { vfp_double_ftosiz, OP_SCALAR|OP_SD },
 };
 
 
@@ -1108,16 +1108,16 @@
 	return FPSCR_IOC;
 }
 
-static u32 (* const fop_fns[16])(int dd, int dn, int dm, u32 fpscr) = {
-	[FOP_TO_IDX(FOP_FMAC)]	= vfp_double_fmac,
-	[FOP_TO_IDX(FOP_FNMAC)]	= vfp_double_fnmac,
-	[FOP_TO_IDX(FOP_FMSC)]	= vfp_double_fmsc,
-	[FOP_TO_IDX(FOP_FNMSC)]	= vfp_double_fnmsc,
-	[FOP_TO_IDX(FOP_FMUL)]	= vfp_double_fmul,
-	[FOP_TO_IDX(FOP_FNMUL)]	= vfp_double_fnmul,
-	[FOP_TO_IDX(FOP_FADD)]	= vfp_double_fadd,
-	[FOP_TO_IDX(FOP_FSUB)]	= vfp_double_fsub,
-	[FOP_TO_IDX(FOP_FDIV)]	= vfp_double_fdiv,
+static struct op fops[16] = {
+	[FOP_TO_IDX(FOP_FMAC)]	= { vfp_double_fmac,  0 },
+	[FOP_TO_IDX(FOP_FNMAC)]	= { vfp_double_fnmac, 0 },
+	[FOP_TO_IDX(FOP_FMSC)]	= { vfp_double_fmsc,  0 },
+	[FOP_TO_IDX(FOP_FNMSC)]	= { vfp_double_fnmsc, 0 },
+	[FOP_TO_IDX(FOP_FMUL)]	= { vfp_double_fmul,  0 },
+	[FOP_TO_IDX(FOP_FNMUL)]	= { vfp_double_fnmul, 0 },
+	[FOP_TO_IDX(FOP_FADD)]	= { vfp_double_fadd,  0 },
+	[FOP_TO_IDX(FOP_FSUB)]	= { vfp_double_fsub,  0 },
+	[FOP_TO_IDX(FOP_FDIV)]	= { vfp_double_fdiv,  0 },
 };
 
 #define FREG_BANK(x)	((x) & 0x0c)
@@ -1131,69 +1131,60 @@
 	unsigned int dn = vfp_get_dn(inst);
 	unsigned int dm = vfp_get_dm(inst);
 	unsigned int vecitr, veclen, vecstride;
-	u32 (*fop)(int, int, s32, u32);
+	struct op *fop;
 
-	veclen = fpscr & FPSCR_LENGTH_MASK;
 	vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
 
+	fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
+
 	/*
 	 * fcvtds takes an sN register number as destination, not dN.
 	 * It also always operates on scalars.
 	 */
-	if ((inst & FEXT_MASK) == FEXT_FCVT) {
-		veclen = 0;
+	if (fop->flags & OP_SD)
 		dest = vfp_get_sd(inst);
-	} else
+	else
 		dest = vfp_get_dd(inst);
 
 	/*
 	 * If destination bank is zero, vector length is always '1'.
 	 * ARM DDI0100F C5.1.3, C5.3.2.
 	 */
-	if (FREG_BANK(dest) == 0)
+	if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
 		veclen = 0;
+	else
+		veclen = fpscr & FPSCR_LENGTH_MASK;
 
 	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
 		 (veclen >> FPSCR_LENGTH_BIT) + 1);
 
-	fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
-	if (!fop)
+	if (!fop->fn)
 		goto invalid;
 
 	for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
 		u32 except;
+		char type;
 
-		if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
-			pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n",
+		type = fop->flags & OP_SD ? 's' : 'd';
+		if (op == FOP_EXT)
+			pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n",
 				 vecitr >> FPSCR_LENGTH_BIT,
-				 dest, dn, dm);
-		else if (op == FOP_EXT)
-			pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
-				 vecitr >> FPSCR_LENGTH_BIT,
-				 dest, dn, dm);
+				 type, dest, dn, dm);
 		else
-			pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
+			pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n",
 				 vecitr >> FPSCR_LENGTH_BIT,
-				 dest, dn, FOP_TO_IDX(op), dm);
+				 type, dest, dn, FOP_TO_IDX(op), dm);
 
-		except = fop(dest, dn, dm, fpscr);
+		except = fop->fn(dest, dn, dm, fpscr);
 		pr_debug("VFP: itr%d: exceptions=%08x\n",
 			 vecitr >> FPSCR_LENGTH_BIT, except);
 
 		exceptions |= except;
 
 		/*
-		 * This ensures that comparisons only operate on scalars;
-		 * comparisons always return with one FPSCR status bit set.
-		 */
-		if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
-			break;
-
-		/*
 		 * CHECK: It appears to be undefined whether we stop when
 		 * we encounter an exception.  We continue.
 		 */
-
 		dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6);
 		dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
 		if (FREG_BANK(dm) != 0)
diff --git a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h
index 6c819ae..7f343a4 100644
--- a/arch/arm/vfp/vfpinstr.h
+++ b/arch/arm/vfp/vfpinstr.h
@@ -73,14 +73,14 @@
 
 #define fmrx(_vfp_) ({			\
 	u32 __v;			\
-	asm("mrc%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx	%0, " #_vfp_	\
-	    : "=r" (__v));		\
+	asm("mrc p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx	%0, " #_vfp_	\
+	    : "=r" (__v) : : "cc");	\
 	__v;				\
  })
 
 #define fmxr(_vfp_,_var_)		\
-	asm("mcr%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr	" #_vfp_ ", %0"	\
-	   : : "r" (_var_))
+	asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr	" #_vfp_ ", %0"	\
+	   : : "r" (_var_) : "cc")
 
 u32 vfp_single_cpdo(u32 inst, u32 fpscr);
 u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs);
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 4178f6c..dedbb44 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -40,10 +40,19 @@
 static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
 	struct thread_info *thread = v;
-	union vfp_state *vfp = &thread->vfpstate;
+	union vfp_state *vfp;
 
-	switch (cmd) {
-	case THREAD_NOTIFY_FLUSH:
+	if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
+		/*
+		 * Always disable VFP so we can lazily save/restore the
+		 * old state.
+		 */
+		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+		return NOTIFY_DONE;
+	}
+
+	vfp = &thread->vfpstate;
+	if (cmd == THREAD_NOTIFY_FLUSH) {
 		/*
 		 * Per-thread VFP initialisation.
 		 */
@@ -56,29 +65,12 @@
 		 * Disable VFP to ensure we initialise it first.
 		 */
 		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
-
-		/*
-		 * FALLTHROUGH: Ensure we don't try to overwrite our newly
-		 * initialised state information on the first fault.
-		 */
-
-	case THREAD_NOTIFY_RELEASE:
-		/*
-		 * Per-thread VFP cleanup.
-		 */
-		if (last_VFP_context == vfp)
-			last_VFP_context = NULL;
-		break;
-
-	case THREAD_NOTIFY_SWITCH:
-		/*
-		 * Always disable VFP so we can lazily save/restore the
-		 * old state.
-		 */
-		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
-		break;
 	}
 
+	/* flush and release case: Per-thread VFP cleanup. */
+	if (last_VFP_context == vfp)
+		last_VFP_context = NULL;
+
 	return NOTIFY_DONE;
 }
 
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index 8f6c179..ab5e950 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -702,22 +702,22 @@
 	return vfp_single_ftosi(sd, unused, m, FPSCR_ROUND_TOZERO);
 }
 
-static u32 (* const fop_extfns[32])(int sd, int unused, s32 m, u32 fpscr) = {
-	[FEXT_TO_IDX(FEXT_FCPY)]	= vfp_single_fcpy,
-	[FEXT_TO_IDX(FEXT_FABS)]	= vfp_single_fabs,
-	[FEXT_TO_IDX(FEXT_FNEG)]	= vfp_single_fneg,
-	[FEXT_TO_IDX(FEXT_FSQRT)]	= vfp_single_fsqrt,
-	[FEXT_TO_IDX(FEXT_FCMP)]	= vfp_single_fcmp,
-	[FEXT_TO_IDX(FEXT_FCMPE)]	= vfp_single_fcmpe,
-	[FEXT_TO_IDX(FEXT_FCMPZ)]	= vfp_single_fcmpz,
-	[FEXT_TO_IDX(FEXT_FCMPEZ)]	= vfp_single_fcmpez,
-	[FEXT_TO_IDX(FEXT_FCVT)]	= vfp_single_fcvtd,
-	[FEXT_TO_IDX(FEXT_FUITO)]	= vfp_single_fuito,
-	[FEXT_TO_IDX(FEXT_FSITO)]	= vfp_single_fsito,
-	[FEXT_TO_IDX(FEXT_FTOUI)]	= vfp_single_ftoui,
-	[FEXT_TO_IDX(FEXT_FTOUIZ)]	= vfp_single_ftouiz,
-	[FEXT_TO_IDX(FEXT_FTOSI)]	= vfp_single_ftosi,
-	[FEXT_TO_IDX(FEXT_FTOSIZ)]	= vfp_single_ftosiz,
+static struct op fops_ext[32] = {
+	[FEXT_TO_IDX(FEXT_FCPY)]	= { vfp_single_fcpy,   0 },
+	[FEXT_TO_IDX(FEXT_FABS)]	= { vfp_single_fabs,   0 },
+	[FEXT_TO_IDX(FEXT_FNEG)]	= { vfp_single_fneg,   0 },
+	[FEXT_TO_IDX(FEXT_FSQRT)]	= { vfp_single_fsqrt,  0 },
+	[FEXT_TO_IDX(FEXT_FCMP)]	= { vfp_single_fcmp,   OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCMPE)]	= { vfp_single_fcmpe,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCMPZ)]	= { vfp_single_fcmpz,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCMPEZ)]	= { vfp_single_fcmpez, OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FCVT)]	= { vfp_single_fcvtd,  OP_SCALAR|OP_DD },
+	[FEXT_TO_IDX(FEXT_FUITO)]	= { vfp_single_fuito,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FSITO)]	= { vfp_single_fsito,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FTOUI)]	= { vfp_single_ftoui,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FTOUIZ)]	= { vfp_single_ftouiz, OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FTOSI)]	= { vfp_single_ftosi,  OP_SCALAR },
+	[FEXT_TO_IDX(FEXT_FTOSIZ)]	= { vfp_single_ftosiz, OP_SCALAR },
 };
 
 
@@ -1151,16 +1151,16 @@
 	return FPSCR_IOC;
 }
 
-static u32 (* const fop_fns[16])(int sd, int sn, s32 m, u32 fpscr) = {
-	[FOP_TO_IDX(FOP_FMAC)]	= vfp_single_fmac,
-	[FOP_TO_IDX(FOP_FNMAC)]	= vfp_single_fnmac,
-	[FOP_TO_IDX(FOP_FMSC)]	= vfp_single_fmsc,
-	[FOP_TO_IDX(FOP_FNMSC)]	= vfp_single_fnmsc,
-	[FOP_TO_IDX(FOP_FMUL)]	= vfp_single_fmul,
-	[FOP_TO_IDX(FOP_FNMUL)]	= vfp_single_fnmul,
-	[FOP_TO_IDX(FOP_FADD)]	= vfp_single_fadd,
-	[FOP_TO_IDX(FOP_FSUB)]	= vfp_single_fsub,
-	[FOP_TO_IDX(FOP_FDIV)]	= vfp_single_fdiv,
+static struct op fops[16] = {
+	[FOP_TO_IDX(FOP_FMAC)]	= { vfp_single_fmac,  0 },
+	[FOP_TO_IDX(FOP_FNMAC)]	= { vfp_single_fnmac, 0 },
+	[FOP_TO_IDX(FOP_FMSC)]	= { vfp_single_fmsc,  0 },
+	[FOP_TO_IDX(FOP_FNMSC)]	= { vfp_single_fnmsc, 0 },
+	[FOP_TO_IDX(FOP_FMUL)]	= { vfp_single_fmul,  0 },
+	[FOP_TO_IDX(FOP_FNMUL)]	= { vfp_single_fnmul, 0 },
+	[FOP_TO_IDX(FOP_FADD)]	= { vfp_single_fadd,  0 },
+	[FOP_TO_IDX(FOP_FSUB)]	= { vfp_single_fsub,  0 },
+	[FOP_TO_IDX(FOP_FDIV)]	= { vfp_single_fdiv,  0 },
 };
 
 #define FREG_BANK(x)	((x) & 0x18)
@@ -1174,70 +1174,63 @@
 	unsigned int sn = vfp_get_sn(inst);
 	unsigned int sm = vfp_get_sm(inst);
 	unsigned int vecitr, veclen, vecstride;
-	u32 (*fop)(int, int, s32, u32);
+	struct op *fop;
 
-	veclen = fpscr & FPSCR_LENGTH_MASK;
 	vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
 
+	fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
+
 	/*
 	 * fcvtsd takes a dN register number as destination, not sN.
 	 * Technically, if bit 0 of dd is set, this is an invalid
 	 * instruction.  However, we ignore this for efficiency.
 	 * It also only operates on scalars.
 	 */
-	if ((inst & FEXT_MASK) == FEXT_FCVT) {
-		veclen = 0;
+	if (fop->flags & OP_DD)
 		dest = vfp_get_dd(inst);
-	} else
+	else
 		dest = vfp_get_sd(inst);
 
 	/*
 	 * If destination bank is zero, vector length is always '1'.
 	 * ARM DDI0100F C5.1.3, C5.3.2.
 	 */
-	if (FREG_BANK(dest) == 0)
+	if ((fop->flags & OP_SCALAR) || FREG_BANK(dest) == 0)
 		veclen = 0;
+	else
+		veclen = fpscr & FPSCR_LENGTH_MASK;
 
 	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
 		 (veclen >> FPSCR_LENGTH_BIT) + 1);
 
-	fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
-	if (!fop)
+	if (!fop->fn)
 		goto invalid;
 
 	for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
 		s32 m = vfp_get_float(sm);
 		u32 except;
+		char type;
 
-		if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
-			pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n",
-				 vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
-		else if (op == FOP_EXT)
-			pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n",
-				 vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
+		type = fop->flags & OP_DD ? 'd' : 's';
+		if (op == FOP_EXT)
+			pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n",
+				 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
+				 sm, m);
 		else
-			pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n",
-				 vecitr >> FPSCR_LENGTH_BIT, dest, sn,
+			pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n",
+				 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
 				 FOP_TO_IDX(op), sm, m);
 
-		except = fop(dest, sn, m, fpscr);
+		except = fop->fn(dest, sn, m, fpscr);
 		pr_debug("VFP: itr%d: exceptions=%08x\n",
 			 vecitr >> FPSCR_LENGTH_BIT, except);
 
 		exceptions |= except;
 
 		/*
-		 * This ensures that comparisons only operate on scalars;
-		 * comparisons always return with one FPSCR status bit set.
-		 */
-		if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
-			break;
-
-		/*
 		 * CHECK: It appears to be undefined whether we stop when
 		 * we encounter an exception.  We continue.
 		 */
-
 		dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
 		sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
 		if (FREG_BANK(sm) != 0)
diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c
index db63d75..80adbd0 100644
--- a/arch/arm26/kernel/time.c
+++ b/arch/arm26/kernel/time.c
@@ -194,7 +194,7 @@
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-        do_timer(regs);
+        do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/arm26/mm/fault.c b/arch/arm26/mm/fault.c
index 761938b..a1f6d8a 100644
--- a/arch/arm26/mm/fault.c
+++ b/arch/arm26/mm/fault.c
@@ -155,7 +155,7 @@
 	 */
 good_area:
 	if (READ_FAULT(fsr)) /* read? */
-		mask = VM_READ|VM_EXEC;
+		mask = VM_READ|VM_EXEC|VM_WRITE;
 	else
 		mask = VM_WRITE;
 
@@ -185,7 +185,7 @@
 	}
 
 	fault = -3; /* out of memory */
-	if (tsk->pid != 1)
+	if (!is_init(tsk))
 		goto out;
 
 	/*
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index b0e6b58..3e56b9f 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -148,7 +148,7 @@
 	 * Call the generic timer interrupt handler
 	 */
 	write_seqlock(&xtime_lock);
-	do_timer(regs);
+	do_timer(1);
 	write_sequnlock(&xtime_lock);
 
 	/*
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index 9c22b76..ebacf14 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -227,7 +227,7 @@
 	
 	/* call the real timer interrupt handler */
 
-	do_timer(regs);
+	do_timer(1);
 	
         cris_do_profile(regs); /* Save profiling information */
 
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c
index 50f3f93..be0a016 100644
--- a/arch/cris/arch-v32/kernel/time.c
+++ b/arch/cris/arch-v32/kernel/time.c
@@ -219,7 +219,7 @@
 		return IRQ_HANDLED;
 
 	/* call the real timer interrupt handler */
-	do_timer(regs);
+	do_timer(1);
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 3d0284b..7e55884 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -70,7 +70,7 @@
 	 */
 	write_seqlock(&xtime_lock);
 
-	do_timer(regs);
+	do_timer(1);
 	update_process_times(user_mode(regs));
 	profile_tick(CPU_PROFILING, regs);
 
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index 688a510..e569d17 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -41,7 +41,7 @@
 	/* may need to kick the hardware timer */
 	platform_timer_eoi();
 
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index ff9ce4b..b42f2d9 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -225,6 +225,7 @@
 #include <linux/smp_lock.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
+#include <linux/kthread.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -402,8 +403,6 @@
 #else
 static int			realmode_power_off;
 #endif
-static int			exit_kapmd __read_mostly;
-static int			kapmd_running __read_mostly;
 #ifdef CONFIG_APM_ALLOW_INTS
 static int			allow_ints = 1;
 #else
@@ -419,6 +418,8 @@
 
 static const char		driver_version[] = "1.16ac";	/* no spaces */
 
+static struct task_struct *kapmd_task;
+
 /*
  *	APM event names taken from the APM 1.2 specification. These are
  *	the message codes that the BIOS uses to tell us about events
@@ -1423,7 +1424,7 @@
 	set_current_state(TASK_INTERRUPTIBLE);
 	for (;;) {
 		schedule_timeout(APM_CHECK_TIMEOUT);
-		if (exit_kapmd)
+		if (kthread_should_stop())
 			break;
 		/*
 		 * Ok, check all events, check for idle (and mark us sleeping
@@ -1706,12 +1707,6 @@
 	char *		power_stat;
 	char *		bat_stat;
 
-	kapmd_running = 1;
-
-	daemonize("kapmd");
-
-	current->flags |= PF_NOFREEZE;
-
 #ifdef CONFIG_SMP
 	/* 2002/08/01 - WT
 	 * This is to avoid random crashes at boot time during initialization
@@ -1821,7 +1816,6 @@
 		console_blank_hook = NULL;
 #endif
 	}
-	kapmd_running = 0;
 
 	return 0;
 }
@@ -2220,7 +2214,7 @@
 {
 	struct proc_dir_entry *apm_proc;
 	struct desc_struct *gdt;
-	int ret;
+	int err;
 
 	dmi_check_system(apm_dmi_table);
 
@@ -2329,12 +2323,17 @@
 	if (apm_proc)
 		apm_proc->owner = THIS_MODULE;
 
-	ret = kernel_thread(apm, NULL, CLONE_KERNEL | SIGCHLD);
-	if (ret < 0) {
-		printk(KERN_ERR "apm: disabled - Unable to start kernel thread.\n");
+	kapmd_task = kthread_create(apm, NULL, "kapmd");
+	if (IS_ERR(kapmd_task)) {
+		printk(KERN_ERR "apm: disabled - Unable to start kernel "
+				"thread.\n");
+		err = PTR_ERR(kapmd_task);
+		kapmd_task = NULL;
 		remove_proc_entry("apm", NULL);
-		return -ENOMEM;
+		return err;
 	}
+	kapmd_task->flags |= PF_NOFREEZE;
+	wake_up_process(kapmd_task);
 
 	if (num_online_cpus() > 1 && !smp ) {
 		printk(KERN_NOTICE
@@ -2384,9 +2383,10 @@
 	remove_proc_entry("apm", NULL);
 	if (power_off)
 		pm_power_off = NULL;
-	exit_kapmd = 1;
-	while (kapmd_running)
-		schedule();
+	if (kapmd_task) {
+		kthread_stop(kapmd_task);
+		kapmd_task = NULL;
+	}
 #ifdef CONFIG_PM_LEGACY
 	pm_active = 0;
 #endif
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index fe15804..f943698 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -65,7 +65,7 @@
 static DEFINE_SPINLOCK(efi_rt_lock);
 static pgd_t efi_bak_pg_dir_pointer[2];
 
-static void efi_call_phys_prelog(void)
+static void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
 {
 	unsigned long cr4;
 	unsigned long temp;
@@ -109,7 +109,7 @@
 	load_gdt(cpu_gdt_descr);
 }
 
-static void efi_call_phys_epilog(void)
+static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
 {
 	unsigned long cr4;
 	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 020d873..82b26d5 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -102,6 +102,8 @@
 			{ [0 ... NR_CPUS-1] = 0xff };
 EXPORT_SYMBOL(x86_cpu_to_apicid);
 
+u8 apicid_2_node[MAX_APICID];
+
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -645,7 +647,7 @@
 {
 	int cpu = smp_processor_id();
 	int apicid = logical_smp_processor_id();
-	int node = apicid_to_node(apicid);
+	int node = apicid_to_node(hard_smp_processor_id());
 
 	if (!node_online(node))
 		node = first_online_node;
@@ -954,6 +956,7 @@
 
 	irq_ctx_init(cpu);
 
+	x86_cpu_to_apicid[cpu] = apicid;
 	/*
 	 * This grunge runs the startup process for
 	 * the targeted processor.
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index 3241312..f7e735c 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -30,6 +30,7 @@
 #include <linux/nodemask.h>
 #include <asm/srat.h>
 #include <asm/topology.h>
+#include <asm/smp.h>
 
 /*
  * proximity macros and definitions
@@ -54,6 +55,7 @@
 static struct node_memory_chunk_s node_memory_chunk[MAXCHUNKS];
 
 static int num_memory_chunks;		/* total number of memory chunks */
+static u8 __initdata apicid_to_pxm[MAX_APICID];
 
 extern void * boot_ioremap(unsigned long, unsigned long);
 
@@ -69,6 +71,8 @@
 	/* mark this node as "seen" in node bitmap */
 	BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain);
 
+	apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain;
+
 	printk("CPU 0x%02X in proximity domain 0x%02X\n",
 		cpu_affinity->apic_id, cpu_affinity->proximity_domain);
 }
@@ -235,6 +239,9 @@
 	printk("Number of logical nodes in system = %d\n", num_online_nodes());
 	printk("Number of memory chunks in system = %d\n", num_memory_chunks);
 
+	for (i = 0; i < MAX_APICID; i++)
+		apicid_2_node[i] = pxm_to_node(apicid_to_pxm[i]);
+
 	for (j = 0; j < num_memory_chunks; j++){
 		struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
 		printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index efc7e7d..08502fc 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -739,7 +739,7 @@
 			retval = get_user_pages(current, current->mm,
 					(unsigned long )to, 1, 1, 0, &pg, NULL);
 
-			if (retval == -ENOMEM && current->pid == 1) {
+			if (retval == -ENOMEM && is_init(current)) {
 				up_read(&current->mm->mmap_sem);
 				blk_congestion_wait(WRITE, HZ/50);
 				goto survive;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 5e17a3f..2581575 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -440,7 +440,7 @@
 		case 1:		/* read, present */
 			goto bad_area;
 		case 0:		/* read, not present */
-			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 				goto bad_area;
 	}
 
@@ -589,7 +589,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (tsk->pid == 1) {
+	if (is_init(tsk)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
index f88e05b..ca2447e 100644
--- a/arch/i386/oprofile/op_model_ppro.c
+++ b/arch/i386/oprofile/op_model_ppro.c
@@ -138,11 +138,14 @@
 static void ppro_start(struct op_msrs const * const msrs)
 {
 	unsigned int low,high;
+	int i;
 
-	if (reset_value[0]) {
-		CTRL_READ(low, high, msrs, 0);
-		CTRL_SET_ACTIVE(low);
-		CTRL_WRITE(low, high, msrs, 0);
+	for (i = 0; i < NUM_COUNTERS; ++i) {
+		if (reset_value[i]) {
+			CTRL_READ(low, high, msrs, i);
+			CTRL_SET_ACTIVE(low);
+			CTRL_WRITE(low, high, msrs, i);
+		}
 	}
 }
 
@@ -150,11 +153,14 @@
 static void ppro_stop(struct op_msrs const * const msrs)
 {
 	unsigned int low,high;
+	int i;
 
-	if (reset_value[0]) {
-		CTRL_READ(low, high, msrs, 0);
+	for (i = 0; i < NUM_COUNTERS; ++i) {
+		if (!reset_value[i])
+			continue;
+		CTRL_READ(low, high, msrs, i);
 		CTRL_SET_INACTIVE(low);
-		CTRL_WRITE(low, high, msrs, 0);
+		CTRL_WRITE(low, high, msrs, i);
 	}
 }
 
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index b5195be..e1a1b11 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -320,7 +320,7 @@
 	}
 
 	printk(KERN_INFO "simeth_device_event: %s ipaddr=0x%x\n",
-	       dev->name, htonl(ifa->ifa_local));
+	       dev->name, ntohl(ifa->ifa_local));
 
 	/*
 	 * XXX Fix me
@@ -331,7 +331,7 @@
 	local = dev->priv;
 	/* now do it for real */
 	r = event == NETDEV_UP ?
-		netdev_attach(local->simfd, dev->irq, htonl(ifa->ifa_local)):
+		netdev_attach(local->simfd, dev->irq, ntohl(ifa->ifa_local)):
 		netdev_detach(local->simfd);
 
 	printk(KERN_INFO "simeth: netdev_attach/detach: event=%s ->%d\n",
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 6928ef0..16262687 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -78,7 +78,7 @@
 			 * xtime_lock.
 			 */
 			write_seqlock(&xtime_lock);
-			do_timer(regs);
+			do_timer(1);
 			local_cpu_data->itm_next = new_itm;
 			write_sequnlock(&xtime_lock);
 		} else
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 14ef7cc..59f3ab9 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -146,9 +146,11 @@
 #		error File is out of sync with <linux/mm.h>.  Please update.
 #	endif
 
+	if (((isr >> IA64_ISR_R_BIT) & 1UL) && (!(vma->vm_flags & (VM_READ | VM_WRITE))))
+		goto bad_area;
+
 	mask = (  (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
-		| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
-		| (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
+		| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
 
 	if ((vma->vm_flags & mask) != mask)
 		goto bad_area;
@@ -278,7 +280,7 @@
 
   out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index ded0be0..7a89689 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -202,7 +202,7 @@
 #ifndef CONFIG_SMP
 	profile_tick(CPU_PROFILING, regs);
 #endif
-	do_timer(regs);
+	do_timer(1);
 
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
index dc18a33..8d5f551 100644
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -299,7 +299,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (tsk->pid == 1) {
+	if (is_init(tsk)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 98e4b1a..1072e49 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -40,7 +40,7 @@
  */
 static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 {
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index aec1527..911f2ce 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -144,7 +144,7 @@
 		case 1:		/* read, present */
 			goto acc_err;
 		case 0:		/* read, not present */
-			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 				goto acc_err;
 	}
 
@@ -181,7 +181,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index f18b9d3..dc4ea7e 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -65,7 +65,7 @@
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
-        do_timer(fp);
+        do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(fp));
 #endif
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index 1db9872..db1e1ce 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -51,7 +51,7 @@
 
 	write_seqlock(&xtime_lock);
 
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index 7fbea1b..0a067f3 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -96,7 +96,7 @@
 		timerlo = count;
 
 		kstat_this_cpu.irqs[irq]++;
-		do_timer(regs);
+		do_timer(1);
 #ifndef CONFIG_SMP
 		update_process_times(user_mode(regs));
 #endif
@@ -137,7 +137,7 @@
 	}
 
 	while (time_elapsed > 0) {
-		do_timer(regs);
+		do_timer(1);
 #ifndef CONFIG_SMP
 		update_process_times(user_mode(regs));
 #endif
@@ -156,7 +156,7 @@
 
 	if (jiffie_drift >= 999) {
 		jiffie_drift -= 999;
-		do_timer(regs); /* increment jiffies by one */
+		do_timer(1); /* increment jiffies by one */
 #ifndef CONFIG_SMP
 		update_process_times(user_mode(regs));
 #endif
diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c
index d837b26..7feca49 100644
--- a/arch/mips/gt64120/common/time.c
+++ b/arch/mips/gt64120/common/time.c
@@ -34,7 +34,7 @@
 	if (irq_src & 0x00000800) {	/* Check for timer interrupt */
 		handled = 1;
 		irq_src &= ~0x00000800;
-		do_timer(regs);
+		do_timer(1);
 #ifndef CONFIG_SMP
 		update_process_times(user_mode(regs));
 #endif
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 170cb67..6ab8d97 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -434,7 +434,7 @@
 	/*
 	 * call the generic timer interrupt handling
 	 */
-	do_timer(regs);
+	do_timer(1);
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index a4f8c45..8423d85 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -171,7 +171,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (tsk->pid == 1) {
+	if (is_init(tsk)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c
index 9fb2493..6cd87cf 100644
--- a/arch/mips/momentum/ocelot_g/gt-irq.c
+++ b/arch/mips/momentum/ocelot_g/gt-irq.c
@@ -133,7 +133,7 @@
 		MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
 
 		/* handle the timer call */
-		do_timer(regs);
+		do_timer(1);
 #ifndef CONFIG_SMP
 		update_process_times(user_mode(regs));
 #endif
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index b029ba7..c62a3a9 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -111,7 +111,7 @@
 	kstat_this_cpu.irqs[irq]++;		/* kstat only for bootcpu? */
 
 	if (cpu == 0)
-		do_timer(regs);
+		do_timer(1);
 
 	update_process_times(user_mode(regs));
 
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index aee3118..f50b982 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -27,7 +27,7 @@
  *    - SEGREL32 handling
  *      We are not doing SEGREL32 handling correctly. According to the ABI, we
  *      should do a value offset, like this:
- *			if (is_init(me, (void *)val))
+ *			if (in_init(me, (void *)val))
  *				val -= (uint32_t)me->module_init;
  *			else
  *				val -= (uint32_t)me->module_core;
@@ -72,27 +72,27 @@
 
 /* three functions to determine where in the module core
  * or init pieces the location is */
-static inline int is_init(struct module *me, void *loc)
+static inline int in_init(struct module *me, void *loc)
 {
 	return (loc >= me->module_init &&
 		loc <= (me->module_init + me->init_size));
 }
 
-static inline int is_core(struct module *me, void *loc)
+static inline int in_core(struct module *me, void *loc)
 {
 	return (loc >= me->module_core &&
 		loc <= (me->module_core + me->core_size));
 }
 
-static inline int is_local(struct module *me, void *loc)
+static inline int in_local(struct module *me, void *loc)
 {
-	return is_init(me, loc) || is_core(me, loc);
+	return in_init(me, loc) || in_core(me, loc);
 }
 
-static inline int is_local_section(struct module *me, void *loc, void *dot)
+static inline int in_local_section(struct module *me, void *loc, void *dot)
 {
-	return (is_init(me, loc) && is_init(me, dot)) ||
-		(is_core(me, loc) && is_core(me, dot));
+	return (in_init(me, loc) && in_init(me, dot)) ||
+		(in_core(me, loc) && in_core(me, dot));
 }
 
 
@@ -566,14 +566,14 @@
 			break;
 		case R_PARISC_PCREL17F:
 			/* 17-bit PC relative address */
-			val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
+			val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
 			val = (val - dot - 8)/4;
 			CHECK_RELOC(val, 17)
 			*loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
 			break;
 		case R_PARISC_PCREL22F:
 			/* 22-bit PC relative address; only defined for pa20 */
-			val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
+			val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
 			DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", 
 			       strtab + sym->st_name, (unsigned long)loc, addend, 
 			       val)
@@ -670,9 +670,9 @@
 			       strtab + sym->st_name,
 			       loc, val);
 			/* can we reach it locally? */
-			if(!is_local_section(me, (void *)val, (void *)dot)) {
+			if(!in_local_section(me, (void *)val, (void *)dot)) {
 
-				if (is_local(me, (void *)val))
+				if (in_local(me, (void *)val))
 					/* this is the case where the
 					 * symbol is local to the
 					 * module, but in a different
@@ -680,14 +680,14 @@
 					 * in case it's more than 22
 					 * bits away */
 					val = get_stub(me, val, addend, ELF_STUB_DIRECT,
-						       is_init(me, loc));
+						       in_init(me, loc));
 				else if (strncmp(strtab + sym->st_name, "$$", 2)
 				    == 0)
 					val = get_stub(me, val, addend, ELF_STUB_MILLI,
-						       is_init(me, loc));
+						       in_init(me, loc));
 				else
 					val = get_stub(me, val, addend, ELF_STUB_GOT,
-						       is_init(me, loc));
+						       in_init(me, loc));
 			}
 			DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 
 			       strtab + sym->st_name, loc, sym->st_value,
@@ -720,7 +720,7 @@
 			break;
 		case R_PARISC_FPTR64:
 			/* 64-bit function address */
-			if(is_local(me, (void *)(val + addend))) {
+			if(in_local(me, (void *)(val + addend))) {
 				*loc64 = get_fdesc(me, val+addend);
 				DEBUGP("FDESC for %s at %p points to %lx\n",
 				       strtab + sym->st_name, *loc64,
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 5facc9b..700df10 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -79,7 +79,7 @@
 #endif
 		if (cpu == 0) {
 			write_seqlock(&xtime_lock);
-			do_timer(regs);
+			do_timer(1);
 			write_sequnlock(&xtime_lock);
 		}
 	}
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 7a3c3f79..71f71da 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -693,7 +693,7 @@
 		tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
 		if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
 			tb_last_jiffy = tb_next_jiffy;
-			do_timer(regs);
+			do_timer(1);
 			timer_recalc_offset(tb_last_jiffy);
 			timer_check_rtc();
 		}
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 78a0d59..e8fa506 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -333,7 +333,7 @@
 		/* protection fault */
 		if (error_code & 0x08000000)
 			goto bad_area;
-		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 			goto bad_area;
 	}
 
@@ -386,7 +386,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 903115d..311ed19 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -337,7 +337,7 @@
 		   err->disposition == RTAS_DISP_NOT_RECOVERED &&
 		   err->target == RTAS_TARGET_MEMORY &&
 		   err->type == RTAS_TYPE_ECC_UNCORR &&
-		   !(current->pid == 0 || current->pid == 1)) {
+		   !(current->pid == 0 || is_init(current))) {
 		/* Kill off a user process with an ECC error */
 		printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
 		       current->pid);
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 6ab8cc7..1e1f315 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -153,7 +153,7 @@
 		/* We are in an interrupt, no need to save/restore flags */
 		write_seqlock(&xtime_lock);
 		tb_last_stamp = jiffy_stamp;
-		do_timer(regs);
+		do_timer(1);
 
 		/*
 		 * update the rtc when needed, this should be performed on the
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index d7a4330..aafc8e8 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -119,7 +119,7 @@
 	 * generate the same exception over and over again and we get
 	 * nowhere.  Better to kill it and let the kernel panic.
 	 */
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		__sighandler_t handler;
 
 		spin_lock_irq(&current->sighand->siglock);
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 5cdfb71..465f451 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -239,7 +239,7 @@
 		/* protection fault */
 		if (error_code & 0x08000000)
 			goto bad_area;
-		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 			goto bad_area;
 	}
 
@@ -291,7 +291,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index b216ca6..f900a51 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -51,6 +51,10 @@
 	  Select this option if you have a 64 bit IBM zSeries machine
 	  and want to use the 64 bit addressing mode.
 
+config 32BIT
+	bool
+	default y if !64BIT
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -149,6 +153,14 @@
 	  This will be slightly faster but does not work on
 	  older machines such as the z900.
 
+config MARCH_Z9_109
+	bool "IBM System z9"
+	help
+	  Select this to enable optimizations for IBM System z9-109, IBM
+	  System z9 Enterprise Class (z9 EC), and IBM System z9 Business
+	  Class (z9 BC). The kernel will be slightly faster but will not
+	  work on older machines such as the z990, z890, z900, and z800.
+
 endchoice
 
 config PACK_STACK
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 74ef57d..5deb9f7 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -33,6 +33,7 @@
 cflags-$(CONFIG_MARCH_G5)   += $(call cc-option,-march=g5)
 cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
 cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
+cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
 
 #
 # Prevent tail-call optimizations, to get clearer backtraces:
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index b69ed74..2b1e6c9 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -16,7 +16,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
-#include <linux/page-flags.h>
+#include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
 #include <linux/sysctl.h>
@@ -157,12 +157,12 @@
 		.prod_nr    = {0xD3, 0xC9, 0xD5, 0xE4,
 			       0xE7, 0xD2, 0xD9},	/* "LINUXKR" */
 		.prod_fn    = 0xD5D3,			/* "NL" */
-		.record_nr  = record_nr,
 		.version_nr = 0xF2F6,			/* "26" */
 		.release_nr = 0xF0F1,			/* "01" */
-		.mod_lvl    = (mod_lvl[0]) << 8 | mod_lvl[1],
 	};
 
+	id.record_nr = record_nr;
+	id.mod_lvl = (mod_lvl[0]) << 8 | mod_lvl[1];
 	return appldata_asm(&id, function, (void *) buffer, length);
 }
 /************************ timer, work, DIAG <END> ****************************/
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index efd836c..2b13708 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -105,63 +105,6 @@
 };
 
 /*
- * Standard fixup and ex_table sections for crypt_s390 inline functions.
- * label 0: the s390 crypto operation
- * label 1: just after 1 to catch illegal operation exception
- *          (unsupported model)
- * label 6: the return point after fixup
- * label 7: set error value if exception _in_ crypto operation
- * label 8: set error value if illegal operation exception
- * [ret] is the variable to receive the error code
- * [ERR] is the error code value
- */
-#ifndef CONFIG_64BIT
-#define __crypt_s390_fixup \
-	".section .fixup,\"ax\" \n"	\
-	"7:	lhi	%0,%h[e1] \n"	\
-	"	bras	1,9f \n"	\
-	"	.long	6b \n"		\
-	"8:	lhi	%0,%h[e2] \n"	\
-	"	bras	1,9f \n"	\
-	"	.long	6b \n"		\
-	"9:	l	1,0(1) \n"	\
-	"	br	1 \n"		\
-	".previous \n"			\
-	".section __ex_table,\"a\" \n"	\
-	"	.align	4 \n"		\
-	"	.long	0b,7b \n"	\
-	"	.long	1b,8b \n"	\
-	".previous"
-#else /* CONFIG_64BIT */
-#define __crypt_s390_fixup \
-	".section .fixup,\"ax\" \n"	\
-	"7:	lhi	%0,%h[e1] \n"	\
-	"	jg	6b \n"		\
-	"8:	lhi	%0,%h[e2] \n"	\
-	"	jg	6b \n"		\
-	".previous\n"			\
-	".section __ex_table,\"a\" \n"	\
-	"	.align	8 \n"		\
-	"	.quad	0b,7b \n"	\
-	"	.quad	1b,8b \n"	\
-	".previous"
-#endif /* CONFIG_64BIT */
-
-/*
- * Standard code for setting the result of s390 crypto instructions.
- * %0: the register which will receive the result
- * [result]: the register containing the result (e.g. second operand length
- * to compute number of processed bytes].
- */
-#ifndef CONFIG_64BIT
-#define __crypt_s390_set_result \
-	"	lr	%0,%[result] \n"
-#else /* CONFIG_64BIT */
-#define __crypt_s390_set_result \
-	"	lgr	%0,%[result] \n"
-#endif
-
-/*
  * Executes the KM (CIPHER MESSAGE) operation of the CPU.
  * @param func: the function code passed to KM; see crypt_s390_km_func
  * @param param: address of parameter block; see POP for details on each func
@@ -176,28 +119,24 @@
 {
 	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
 	register void* __param asm("1") = param;
-	register u8* __dest asm("4") = dest;
 	register const u8* __src asm("2") = src;
 	register long __src_len asm("3") = src_len;
+	register u8* __dest asm("4") = dest;
 	int ret;
 
-	ret = 0;
-	__asm__ __volatile__ (
-		"0:	.insn	rre,0xB92E0000,%1,%2 \n" /* KM opcode */
+	asm volatile(
+		"0:	.insn	rre,0xb92e0000,%3,%1 \n" /* KM opcode */
 		"1:	brc	1,0b \n" /* handle partial completion */
-		__crypt_s390_set_result
-		"6:	\n"
-		__crypt_s390_fixup
-		: "+d" (ret), "+a" (__dest), "+a" (__src),
-		  [result] "+d" (__src_len)
-		: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-		  "a" (__param)
-		: "cc", "memory"
-	);
-	if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-		ret = src_len - ret;
-	}
-	return ret;
+		"	ahi	%0,%h7\n"
+		"2:	ahi	%0,%h8\n"
+		"3:\n"
+		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
+		: "d" (__func), "a" (__param), "0" (-EFAULT),
+		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -215,28 +154,24 @@
 {
 	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
 	register void* __param asm("1") = param;
-	register u8* __dest asm("4") = dest;
 	register const u8* __src asm("2") = src;
 	register long __src_len asm("3") = src_len;
+	register u8* __dest asm("4") = dest;
 	int ret;
 
-	ret = 0;
-	__asm__ __volatile__ (
-		"0:	.insn	rre,0xB92F0000,%1,%2 \n" /* KMC opcode */
+	asm volatile(
+		"0:	.insn	rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
 		"1:	brc	1,0b \n" /* handle partial completion */
-		__crypt_s390_set_result
-		"6:	\n"
-		__crypt_s390_fixup
-		: "+d" (ret), "+a" (__dest), "+a" (__src),
-		  [result] "+d" (__src_len)
-		: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-		  "a" (__param)
-		: "cc", "memory"
-	);
-	if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-		ret = src_len - ret;
-	}
-	return ret;
+		"	ahi	%0,%h7\n"
+		"2:	ahi	%0,%h8\n"
+		"3:\n"
+		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
+		: "d" (__func), "a" (__param), "0" (-EFAULT),
+		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -258,22 +193,19 @@
 	register long __src_len asm("3") = src_len;
 	int ret;
 
-	ret = 0;
-	__asm__ __volatile__ (
-		"0:	.insn	rre,0xB93E0000,%1,%1 \n" /* KIMD opcode */
-		"1:	brc	1,0b \n" /* handle partical completion */
-		__crypt_s390_set_result
-		"6:	\n"
-		__crypt_s390_fixup
-		: "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
-		: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-		  "a" (__param)
-		: "cc", "memory"
-	);
-	if (ret >= 0 && (func & CRYPT_S390_FUNC_MASK)){
-		ret = src_len - ret;
-	}
-	return ret;
+	asm volatile(
+		"0:	.insn	rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
+		"1:	brc	1,0b \n" /* handle partial completion */
+		"	ahi	%0,%h6\n"
+		"2:	ahi	%0,%h7\n"
+		"3:\n"
+		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len)
+		: "d" (__func), "a" (__param), "0" (-EFAULT),
+		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -294,22 +226,19 @@
 	register long __src_len asm("3") = src_len;
 	int ret;
 
-	ret = 0;
-	__asm__ __volatile__ (
-		"0:	.insn	rre,0xB93F0000,%1,%1 \n" /* KLMD opcode */
-		"1:	brc	1,0b \n" /* handle partical completion */
-		__crypt_s390_set_result
-		"6:	\n"
-		__crypt_s390_fixup
-		: "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
-		: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-		  "a" (__param)
-		: "cc", "memory"
-	);
-	if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-		ret = src_len - ret;
-	}
-	return ret;
+	asm volatile(
+		"0:	.insn	rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
+		"1:	brc	1,0b \n" /* handle partial completion */
+		"	ahi	%0,%h6\n"
+		"2:	ahi	%0,%h7\n"
+		"3:\n"
+		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len)
+		: "d" (__func), "a" (__param), "0" (-EFAULT),
+		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -331,22 +260,19 @@
 	register long __src_len asm("3") = src_len;
 	int ret;
 
-	ret = 0;
-	__asm__ __volatile__ (
-		"0:	.insn	rre,0xB91E0000,%5,%5 \n" /* KMAC opcode */
-		"1:	brc	1,0b \n" /* handle partical completion */
-		__crypt_s390_set_result
-		"6:	\n"
-		__crypt_s390_fixup
-		: "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
-		: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-		  "a" (__param)
-		: "cc", "memory"
-	);
-	if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-		ret = src_len - ret;
-	}
-	return ret;
+	asm volatile(
+		"0:	.insn	rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
+		"1:	brc	1,0b \n" /* handle partial completion */
+		"	ahi	%0,%h6\n"
+		"2:	ahi	%0,%h7\n"
+		"3:\n"
+		EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+		: "=d" (ret), "+a" (__src), "+d" (__src_len)
+		: "d" (__func), "a" (__param), "0" (-EFAULT),
+		  "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+	if (ret < 0)
+		return ret;
+	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /**
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 75144ef..443fa37 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -333,22 +333,14 @@
 	register unsigned long _subcode asm("0") = subcode;
 	register unsigned long _size asm("1") = size;
 
-	asm volatile ("   diag    %2,%0,0x204\n"
-		      "0: \n" ".section __ex_table,\"a\"\n"
-#ifndef __s390x__
-		      "    .align 4\n"
-		      "    .long  0b,0b\n"
-#else
-		      "    .align 8\n"
-		      "    .quad  0b,0b\n"
-#endif
-		      ".previous":"+d" (_subcode), "+d"(_size)
-		      :"d"(addr)
-		      :"memory");
+	asm volatile(
+		"	diag	%2,%0,0x204\n"
+		"0:\n"
+		EX_TABLE(0b,0b)
+		: "+d" (_subcode), "+d" (_size) : "d" (addr) : "memory");
 	if (_subcode)
 		return -1;
-	else
-		return _size;
+	return _size;
 }
 
 /*
@@ -403,7 +395,8 @@
 		*pages = 1;
 		return diag204_alloc_rbuf();
 	} else {/* INFO_EXT */
-		*pages = diag204(SUBC_RSI | INFO_EXT, 0, NULL);
+		*pages = diag204((unsigned long)SUBC_RSI |
+				 (unsigned long)INFO_EXT, 0, NULL);
 		if (*pages <= 0)
 			return ERR_PTR(-ENOSYS);
 		else
@@ -490,8 +483,7 @@
 
 static void diag224(void *ptr)
 {
-	asm volatile("   diag    %0,%1,0x224\n"
-		     : :"d" (0), "d"(ptr) : "memory");
+	asm volatile("diag %0,%1,0x224" : :"d" (0), "d"(ptr) : "memory");
 }
 
 static int diag224_get_name_table(void)
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 91b2884..c46e3d4 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -544,10 +544,7 @@
 		current->ptrace &= ~PT_DTRACE;
 		task_unlock(current);
 		current->thread.fp_regs.fpc=0;
-		__asm__ __volatile__
-		        ("sr  0,0\n\t"
-		         "sfpc 0,0\n\t"
-			 : : :"0");
+		asm volatile("sfpc %0,0" : : "d" (0));
 	}
         putname(filename);
 out:
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 4d53b27..4aabeea 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -4,97 +4,97 @@
 *
 *    Copyright (C) IBM Corp. 2000,2006
 *    Author(s): Gerhard Tonn (ton@de.ibm.com),
-*               Thomas Spatzier (tspat@de.ibm.com)
-*/ 
+*		Thomas Spatzier (tspat@de.ibm.com)
+*/
 
-	.globl  sys32_exit_wrapper 
+	.globl	sys32_exit_wrapper
 sys32_exit_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_exit		# branch to sys_exit
-    
-	.globl  sys32_read_wrapper 
+
+	.globl	sys32_read_wrapper
 sys32_read_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# char *
 	llgfr	%r4,%r4			# size_t
 	jg	sys32_read		# branch to sys_read
 
-	.globl  sys32_write_wrapper 
+	.globl	sys32_write_wrapper
 sys32_write_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# size_t
 	jg	sys32_write		# branch to system call
 
-	.globl  sys32_open_wrapper 
+	.globl	sys32_open_wrapper
 sys32_open_wrapper:
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
 	jg	sys_open		# branch to system call
 
-	.globl  sys32_close_wrapper 
+	.globl	sys32_close_wrapper
 sys32_close_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_close		# branch to system call
 
-	.globl  sys32_creat_wrapper 
+	.globl	sys32_creat_wrapper
 sys32_creat_wrapper:
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_creat		# branch to system call
 
-	.globl  sys32_link_wrapper 
+	.globl	sys32_link_wrapper
 sys32_link_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_link		# branch to system call
 
-	.globl  sys32_unlink_wrapper 
+	.globl	sys32_unlink_wrapper
 sys32_unlink_wrapper:
 	llgtr	%r2,%r2			# const char *
 	jg	sys_unlink		# branch to system call
 
-	.globl  sys32_chdir_wrapper 
+	.globl	sys32_chdir_wrapper
 sys32_chdir_wrapper:
 	llgtr	%r2,%r2			# const char *
 	jg	sys_chdir		# branch to system call
 
-	.globl  sys32_time_wrapper 
+	.globl	sys32_time_wrapper
 sys32_time_wrapper:
 	llgtr	%r2,%r2			# int *
 	jg	compat_sys_time		# branch to system call
 
-	.globl  sys32_mknod_wrapper 
+	.globl	sys32_mknod_wrapper
 sys32_mknod_wrapper:
 	llgtr	%r2,%r2			# const char *
-	lgfr	%r3,%r3			# int 
+	lgfr	%r3,%r3			# int
 	llgfr	%r4,%r4			# dev
 	jg	sys_mknod		# branch to system call
 
-	.globl  sys32_chmod_wrapper 
+	.globl	sys32_chmod_wrapper
 sys32_chmod_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# mode_t
 	jg	sys_chmod		# branch to system call
 
-	.globl  sys32_lchown16_wrapper 
+	.globl	sys32_lchown16_wrapper
 sys32_lchown16_wrapper:
 	llgtr	%r2,%r2			# const char *
-	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
-	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t 
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
+	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t
 	jg	sys32_lchown16		# branch to system call
 
-	.globl  sys32_lseek_wrapper 
+	.globl	sys32_lseek_wrapper
 sys32_lseek_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	lgfr	%r3,%r3			# off_t
 	llgfr	%r4,%r4			# unsigned int
 	jg	sys_lseek		# branch to system call
 
-#sys32_getpid_wrapper				# void 
+#sys32_getpid_wrapper				# void
 
-	.globl  sys32_mount_wrapper 
+	.globl	sys32_mount_wrapper
 sys32_mount_wrapper:
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
@@ -103,19 +103,19 @@
 	llgtr	%r6,%r6			# void *
 	jg	compat_sys_mount	# branch to system call
 
-	.globl  sys32_oldumount_wrapper 
+	.globl	sys32_oldumount_wrapper
 sys32_oldumount_wrapper:
 	llgtr	%r2,%r2			# char *
 	jg	sys_oldumount		# branch to system call
 
-	.globl  sys32_setuid16_wrapper 
+	.globl	sys32_setuid16_wrapper
 sys32_setuid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
 	jg	sys32_setuid16		# branch to system call
 
-#sys32_getuid16_wrapper			# void 
+#sys32_getuid16_wrapper			# void
 
-	.globl  sys32_ptrace_wrapper 
+	.globl	sys32_ptrace_wrapper
 sys32_ptrace_wrapper:
 	lgfr	%r2,%r2			# long
 	lgfr	%r3,%r3			# long
@@ -123,168 +123,168 @@
 	llgfr	%r5,%r5			# long
 	jg	sys_ptrace		# branch to system call
 
-	.globl  sys32_alarm_wrapper 
+	.globl	sys32_alarm_wrapper
 sys32_alarm_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_alarm		# branch to system call
 
-#sys32_pause_wrapper			# void 
+#sys32_pause_wrapper			# void
 
-	.globl  compat_sys_utime_wrapper 
+	.globl	compat_sys_utime_wrapper
 compat_sys_utime_wrapper:
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct compat_utimbuf *
 	jg	compat_sys_utime	# branch to system call
 
-	.globl  sys32_access_wrapper 
+	.globl	sys32_access_wrapper
 sys32_access_wrapper:
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_access		# branch to system call
 
-	.globl  sys32_nice_wrapper 
+	.globl	sys32_nice_wrapper
 sys32_nice_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_nice		# branch to system call
 
-#sys32_sync_wrapper			# void 
+#sys32_sync_wrapper			# void
 
-	.globl  sys32_kill_wrapper 
+	.globl	sys32_kill_wrapper
 sys32_kill_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_kill		# branch to system call
 
-	.globl  sys32_rename_wrapper 
+	.globl	sys32_rename_wrapper
 sys32_rename_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_rename		# branch to system call
 
-	.globl  sys32_mkdir_wrapper 
+	.globl	sys32_mkdir_wrapper
 sys32_mkdir_wrapper:
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_mkdir		# branch to system call
 
-	.globl  sys32_rmdir_wrapper 
+	.globl	sys32_rmdir_wrapper
 sys32_rmdir_wrapper:
 	llgtr	%r2,%r2			# const char *
 	jg	sys_rmdir		# branch to system call
 
-	.globl  sys32_dup_wrapper 
+	.globl	sys32_dup_wrapper
 sys32_dup_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_dup			# branch to system call
 
-	.globl  sys32_pipe_wrapper 
+	.globl	sys32_pipe_wrapper
 sys32_pipe_wrapper:
 	llgtr	%r2,%r2			# u32 *
 	jg	sys_pipe		# branch to system call
 
-	.globl  compat_sys_times_wrapper 
+	.globl	compat_sys_times_wrapper
 compat_sys_times_wrapper:
 	llgtr	%r2,%r2			# struct compat_tms *
 	jg	compat_sys_times	# branch to system call
 
-	.globl  sys32_brk_wrapper 
+	.globl	sys32_brk_wrapper
 sys32_brk_wrapper:
 	llgtr	%r2,%r2			# unsigned long
 	jg	sys_brk			# branch to system call
 
-	.globl  sys32_setgid16_wrapper 
+	.globl	sys32_setgid16_wrapper
 sys32_setgid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
 	jg	sys32_setgid16		# branch to system call
 
-#sys32_getgid16_wrapper			# void 
+#sys32_getgid16_wrapper			# void
 
 	.globl sys32_signal_wrapper
 sys32_signal_wrapper:
-	lgfr	%r2,%r2			# int 
+	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# __sighandler_t
 	jg	sys_signal
 
-#sys32_geteuid16_wrapper		# void 
+#sys32_geteuid16_wrapper		# void
 
-#sys32_getegid16_wrapper		# void 
+#sys32_getegid16_wrapper		# void
 
-	.globl  sys32_acct_wrapper 
+	.globl	sys32_acct_wrapper
 sys32_acct_wrapper:
 	llgtr	%r2,%r2			# char *
 	jg	sys_acct		# branch to system call
 
-	.globl  sys32_umount_wrapper 
+	.globl	sys32_umount_wrapper
 sys32_umount_wrapper:
 	llgtr	%r2,%r2			# char *
 	lgfr	%r3,%r3			# int
 	jg	sys_umount		# branch to system call
 
-	.globl  compat_sys_ioctl_wrapper
+	.globl	compat_sys_ioctl_wrapper
 compat_sys_ioctl_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	llgfr	%r4,%r4			# unsigned int
 	jg	compat_sys_ioctl	# branch to system call
 
-	.globl  compat_sys_fcntl_wrapper 
+	.globl	compat_sys_fcntl_wrapper
 compat_sys_fcntl_wrapper:
 	llgfr	%r2,%r2			# unsigned int
-	llgfr	%r3,%r3			# unsigned int 
+	llgfr	%r3,%r3			# unsigned int
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_fcntl	# branch to system call
 
-	.globl  sys32_setpgid_wrapper 
+	.globl	sys32_setpgid_wrapper
 sys32_setpgid_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	lgfr	%r3,%r3			# pid_t
 	jg	sys_setpgid		# branch to system call
 
-	.globl  sys32_umask_wrapper 
+	.globl	sys32_umask_wrapper
 sys32_umask_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_umask		# branch to system call
 
-	.globl  sys32_chroot_wrapper 
+	.globl	sys32_chroot_wrapper
 sys32_chroot_wrapper:
 	llgtr	%r2,%r2			# char *
 	jg	sys_chroot		# branch to system call
 
 	.globl sys32_ustat_wrapper
 sys32_ustat_wrapper:
-	llgfr	%r2,%r2			# dev_t 
+	llgfr	%r2,%r2			# dev_t
 	llgtr	%r3,%r3			# struct ustat *
 	jg	sys_ustat
 
-	.globl  sys32_dup2_wrapper 
+	.globl	sys32_dup2_wrapper
 sys32_dup2_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	jg	sys_dup2		# branch to system call
 
-#sys32_getppid_wrapper			# void 
+#sys32_getppid_wrapper			# void
 
-#sys32_getpgrp_wrapper			# void 
+#sys32_getpgrp_wrapper			# void
 
-#sys32_setsid_wrapper			# void 
+#sys32_setsid_wrapper			# void
 
-	.globl  sys32_sigaction_wrapper
+	.globl	sys32_sigaction_wrapper
 sys32_sigaction_wrapper:
-	lgfr	%r2,%r2			# int 
+	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct old_sigaction *
 	llgtr	%r4,%r4			# struct old_sigaction32 *
 	jg	sys32_sigaction		# branch to system call
 
-	.globl  sys32_setreuid16_wrapper 
+	.globl	sys32_setreuid16_wrapper
 sys32_setreuid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
-	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
 	jg	sys32_setreuid16	# branch to system call
 
-	.globl  sys32_setregid16_wrapper 
+	.globl	sys32_setregid16_wrapper
 sys32_setregid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
-	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
+	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t
 	jg	sys32_setregid16	# branch to system call
 
 	.globl sys_sigsuspend_wrapper
@@ -294,95 +294,95 @@
 	llgfr	%r4,%r4			# old_sigset_t
 	jg	sys_sigsuspend
 
-	.globl  compat_sys_sigpending_wrapper 
+	.globl	compat_sys_sigpending_wrapper
 compat_sys_sigpending_wrapper:
 	llgtr	%r2,%r2			# compat_old_sigset_t *
 	jg	compat_sys_sigpending	# branch to system call
 
-	.globl  sys32_sethostname_wrapper 
+	.globl	sys32_sethostname_wrapper
 sys32_sethostname_wrapper:
 	llgtr	%r2,%r2			# char *
 	lgfr	%r3,%r3			# int
 	jg	sys_sethostname		# branch to system call
 
-	.globl  compat_sys_setrlimit_wrapper 
+	.globl	compat_sys_setrlimit_wrapper
 compat_sys_setrlimit_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct rlimit_emu31 *
 	jg	compat_sys_setrlimit	# branch to system call
 
-	.globl  compat_sys_old_getrlimit_wrapper 
+	.globl	compat_sys_old_getrlimit_wrapper
 compat_sys_old_getrlimit_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct rlimit_emu31 *
 	jg	compat_sys_old_getrlimit # branch to system call
 
-	.globl  compat_sys_getrlimit_wrapper 
+	.globl	compat_sys_getrlimit_wrapper
 compat_sys_getrlimit_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct rlimit_emu31 *
 	jg	compat_sys_getrlimit	# branch to system call
 
-	.globl  sys32_mmap2_wrapper 
+	.globl	sys32_mmap2_wrapper
 sys32_mmap2_wrapper:
 	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 *
 	jg	sys32_mmap2			# branch to system call
 
-	.globl  compat_sys_getrusage_wrapper 
+	.globl	compat_sys_getrusage_wrapper
 compat_sys_getrusage_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct rusage_emu31 *
 	jg	compat_sys_getrusage	# branch to system call
 
-	.globl  sys32_gettimeofday_wrapper 
+	.globl	sys32_gettimeofday_wrapper
 sys32_gettimeofday_wrapper:
 	llgtr	%r2,%r2			# struct timeval_emu31 *
 	llgtr	%r3,%r3			# struct timezone *
 	jg	sys32_gettimeofday	# branch to system call
 
-	.globl  sys32_settimeofday_wrapper 
+	.globl	sys32_settimeofday_wrapper
 sys32_settimeofday_wrapper:
 	llgtr	%r2,%r2			# struct timeval_emu31 *
 	llgtr	%r3,%r3			# struct timezone *
 	jg	sys32_settimeofday	# branch to system call
 
-	.globl  sys32_getgroups16_wrapper 
+	.globl	sys32_getgroups16_wrapper
 sys32_getgroups16_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
 	jg	sys32_getgroups16	# branch to system call
 
-	.globl  sys32_setgroups16_wrapper 
+	.globl	sys32_setgroups16_wrapper
 sys32_setgroups16_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
 	jg	sys32_setgroups16	# branch to system call
 
-	.globl  sys32_symlink_wrapper 
+	.globl	sys32_symlink_wrapper
 sys32_symlink_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_symlink		# branch to system call
 
-	.globl  sys32_readlink_wrapper 
+	.globl	sys32_readlink_wrapper
 sys32_readlink_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# char *
 	lgfr	%r4,%r4			# int
 	jg	sys_readlink		# branch to system call
 
-	.globl  sys32_uselib_wrapper 
+	.globl	sys32_uselib_wrapper
 sys32_uselib_wrapper:
 	llgtr	%r2,%r2			# const char *
 	jg	sys_uselib		# branch to system call
 
-	.globl  sys32_swapon_wrapper 
+	.globl	sys32_swapon_wrapper
 sys32_swapon_wrapper:
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_swapon		# branch to system call
 
-	.globl  sys32_reboot_wrapper 
+	.globl	sys32_reboot_wrapper
 sys32_reboot_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
@@ -390,121 +390,121 @@
 	llgtr	%r5,%r5			# void *
 	jg	sys_reboot		# branch to system call
 
-	.globl  old32_readdir_wrapper 
+	.globl	old32_readdir_wrapper
 old32_readdir_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# void *
 	llgfr	%r4,%r4			# unsigned int
 	jg	compat_sys_old_readdir	# branch to system call
 
-	.globl  old32_mmap_wrapper 
+	.globl	old32_mmap_wrapper
 old32_mmap_wrapper:
 	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 *
 	jg	old32_mmap		# branch to system call
 
-	.globl  sys32_munmap_wrapper 
+	.globl	sys32_munmap_wrapper
 sys32_munmap_wrapper:
 	llgfr	%r2,%r2			# unsigned long
-	llgfr	%r3,%r3			# size_t 
+	llgfr	%r3,%r3			# size_t
 	jg	sys_munmap		# branch to system call
 
-	.globl  sys32_truncate_wrapper 
+	.globl	sys32_truncate_wrapper
 sys32_truncate_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# unsigned long
 	jg	sys_truncate		# branch to system call
 
-	.globl  sys32_ftruncate_wrapper 
+	.globl	sys32_ftruncate_wrapper
 sys32_ftruncate_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned long
 	jg	sys_ftruncate		# branch to system call
 
-	.globl  sys32_fchmod_wrapper 
+	.globl	sys32_fchmod_wrapper
 sys32_fchmod_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# mode_t
 	jg	sys_fchmod		# branch to system call
 
-	.globl  sys32_fchown16_wrapper 
+	.globl	sys32_fchown16_wrapper
 sys32_fchown16_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# compat_uid_t
 	llgfr	%r4,%r4			# compat_uid_t
 	jg	sys32_fchown16		# branch to system call
 
-	.globl  sys32_getpriority_wrapper 
+	.globl	sys32_getpriority_wrapper
 sys32_getpriority_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_getpriority		# branch to system call
 
-	.globl  sys32_setpriority_wrapper 
+	.globl	sys32_setpriority_wrapper
 sys32_setpriority_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
 	jg	sys_setpriority		# branch to system call
 
-	.globl  compat_sys_statfs_wrapper 
+	.globl	compat_sys_statfs_wrapper
 compat_sys_statfs_wrapper:
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct compat_statfs *
 	jg	compat_sys_statfs	# branch to system call
 
-	.globl  compat_sys_fstatfs_wrapper 
+	.globl	compat_sys_fstatfs_wrapper
 compat_sys_fstatfs_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct compat_statfs *
 	jg	compat_sys_fstatfs	# branch to system call
 
-	.globl  compat_sys_socketcall_wrapper 
+	.globl	compat_sys_socketcall_wrapper
 compat_sys_socketcall_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# u32 *
 	jg	compat_sys_socketcall	# branch to system call
 
-	.globl  sys32_syslog_wrapper 
+	.globl	sys32_syslog_wrapper
 sys32_syslog_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# char *
 	lgfr	%r4,%r4			# int
 	jg	sys_syslog		# branch to system call
 
-	.globl  compat_sys_setitimer_wrapper 
+	.globl	compat_sys_setitimer_wrapper
 compat_sys_setitimer_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct itimerval_emu31 *
 	llgtr	%r4,%r4			# struct itimerval_emu31 *
 	jg	compat_sys_setitimer	# branch to system call
 
-	.globl  compat_sys_getitimer_wrapper 
+	.globl	compat_sys_getitimer_wrapper
 compat_sys_getitimer_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct itimerval_emu31 *
 	jg	compat_sys_getitimer	# branch to system call
 
-	.globl  compat_sys_newstat_wrapper 
+	.globl	compat_sys_newstat_wrapper
 compat_sys_newstat_wrapper:
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct stat_emu31 *
 	jg	compat_sys_newstat	# branch to system call
 
-	.globl  compat_sys_newlstat_wrapper 
+	.globl	compat_sys_newlstat_wrapper
 compat_sys_newlstat_wrapper:
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct stat_emu31 *
 	jg	compat_sys_newlstat	# branch to system call
 
-	.globl  compat_sys_newfstat_wrapper 
+	.globl	compat_sys_newfstat_wrapper
 compat_sys_newfstat_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct stat_emu31 *
 	jg	compat_sys_newfstat	# branch to system call
 
-#sys32_vhangup_wrapper			# void 
+#sys32_vhangup_wrapper			# void
 
-	.globl  compat_sys_wait4_wrapper 
+	.globl	compat_sys_wait4_wrapper
 compat_sys_wait4_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# unsigned int *
@@ -512,17 +512,17 @@
 	llgtr	%r5,%r5			# struct rusage *
 	jg	compat_sys_wait4	# branch to system call
 
-	.globl  sys32_swapoff_wrapper 
+	.globl	sys32_swapoff_wrapper
 sys32_swapoff_wrapper:
 	llgtr	%r2,%r2			# const char *
 	jg	sys_swapoff		# branch to system call
 
-	.globl  sys32_sysinfo_wrapper 
+	.globl	sys32_sysinfo_wrapper
 sys32_sysinfo_wrapper:
 	llgtr	%r2,%r2			# struct sysinfo_emu31 *
 	jg	sys32_sysinfo		# branch to system call
 
-	.globl  sys32_ipc_wrapper 
+	.globl	sys32_ipc_wrapper
 sys32_ipc_wrapper:
 	llgfr	%r2,%r2			# uint
 	lgfr	%r3,%r3			# int
@@ -531,59 +531,59 @@
 	llgfr	%r6,%r6			# u32
 	jg	sys32_ipc		# branch to system call
 
-	.globl  sys32_fsync_wrapper 
+	.globl	sys32_fsync_wrapper
 sys32_fsync_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_fsync		# branch to system call
 
-#sys32_sigreturn_wrapper		# done in sigreturn_glue 
+#sys32_sigreturn_wrapper		# done in sigreturn_glue
 
-#sys32_clone_wrapper			# done in clone_glue 
+#sys32_clone_wrapper			# done in clone_glue
 
-	.globl  sys32_setdomainname_wrapper 
+	.globl	sys32_setdomainname_wrapper
 sys32_setdomainname_wrapper:
 	llgtr	%r2,%r2			# char *
 	lgfr	%r3,%r3			# int
 	jg	sys_setdomainname	# branch to system call
 
-	.globl  sys32_newuname_wrapper 
+	.globl	sys32_newuname_wrapper
 sys32_newuname_wrapper:
 	llgtr	%r2,%r2			# struct new_utsname *
 	jg	s390x_newuname		# branch to system call
 
-	.globl  compat_sys_adjtimex_wrapper
+	.globl	compat_sys_adjtimex_wrapper
 compat_sys_adjtimex_wrapper:
 	llgtr	%r2,%r2			# struct compat_timex *
 	jg	compat_sys_adjtimex	# branch to system call
 
-	.globl  sys32_mprotect_wrapper 
+	.globl	sys32_mprotect_wrapper
 sys32_mprotect_wrapper:
 	llgtr	%r2,%r2			# unsigned long (actually pointer
 	llgfr	%r3,%r3			# size_t
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys_mprotect		# branch to system call
 
-	.globl  compat_sys_sigprocmask_wrapper 
+	.globl	compat_sys_sigprocmask_wrapper
 compat_sys_sigprocmask_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_old_sigset_t *
 	llgtr	%r4,%r4			# compat_old_sigset_t *
 	jg	compat_sys_sigprocmask		# branch to system call
 
-	.globl  sys32_init_module_wrapper 
+	.globl	sys32_init_module_wrapper
 sys32_init_module_wrapper:
 	llgtr	%r2,%r2			# void *
 	llgfr	%r3,%r3			# unsigned long
 	llgtr	%r4,%r4			# char *
 	jg	sys32_init_module	# branch to system call
 
-	.globl  sys32_delete_module_wrapper 
+	.globl	sys32_delete_module_wrapper
 sys32_delete_module_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# unsigned int
 	jg	sys32_delete_module	# branch to system call
 
-	.globl  sys32_quotactl_wrapper 
+	.globl	sys32_quotactl_wrapper
 sys32_quotactl_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# const char *
@@ -591,45 +591,45 @@
 	llgtr	%r5,%r5			# caddr_t
 	jg	sys_quotactl		# branch to system call
 
-	.globl  sys32_getpgid_wrapper 
+	.globl	sys32_getpgid_wrapper
 sys32_getpgid_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	jg	sys_getpgid		# branch to system call
 
-	.globl  sys32_fchdir_wrapper 
+	.globl	sys32_fchdir_wrapper
 sys32_fchdir_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_fchdir		# branch to system call
 
-	.globl  sys32_bdflush_wrapper 
+	.globl	sys32_bdflush_wrapper
 sys32_bdflush_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# long
 	jg	sys_bdflush		# branch to system call
 
-	.globl  sys32_sysfs_wrapper 
+	.globl	sys32_sysfs_wrapper
 sys32_sysfs_wrapper:
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys_sysfs		# branch to system call
 
-	.globl  sys32_personality_wrapper 
+	.globl	sys32_personality_wrapper
 sys32_personality_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	jg	s390x_personality	# branch to system call
 
-	.globl  sys32_setfsuid16_wrapper 
+	.globl	sys32_setfsuid16_wrapper
 sys32_setfsuid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
 	jg	sys32_setfsuid16	# branch to system call
 
-	.globl  sys32_setfsgid16_wrapper 
+	.globl	sys32_setfsgid16_wrapper
 sys32_setfsgid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
 	jg	sys32_setfsgid16	# branch to system call
 
-	.globl  sys32_llseek_wrapper 
+	.globl	sys32_llseek_wrapper
 sys32_llseek_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned long
@@ -638,14 +638,14 @@
 	llgfr	%r6,%r6			# unsigned int
 	jg	sys_llseek		# branch to system call
 
-	.globl  sys32_getdents_wrapper 
+	.globl	sys32_getdents_wrapper
 sys32_getdents_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# void *
 	llgfr	%r4,%r4			# unsigned int
 	jg	compat_sys_getdents	# branch to system call
 
-	.globl  compat_sys_select_wrapper
+	.globl	compat_sys_select_wrapper
 compat_sys_select_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_fd_set *
@@ -654,113 +654,113 @@
 	llgtr	%r6,%r6			# struct compat_timeval *
 	jg	compat_sys_select	# branch to system call
 
-	.globl  sys32_flock_wrapper 
+	.globl	sys32_flock_wrapper
 sys32_flock_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	jg	sys_flock		# branch to system call
 
-	.globl  sys32_msync_wrapper 
+	.globl	sys32_msync_wrapper
 sys32_msync_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	lgfr	%r4,%r4			# int
 	jg	sys_msync		# branch to system call
 
-	.globl  compat_sys_readv_wrapper
+	.globl	compat_sys_readv_wrapper
 compat_sys_readv_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct compat_iovec *
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_readv	# branch to system call
 
-	.globl  compat_sys_writev_wrapper
+	.globl	compat_sys_writev_wrapper
 compat_sys_writev_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct compat_iovec *
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_writev	# branch to system call
 
-	.globl  sys32_getsid_wrapper 
+	.globl	sys32_getsid_wrapper
 sys32_getsid_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	jg	sys_getsid		# branch to system call
 
-	.globl  sys32_fdatasync_wrapper 
+	.globl	sys32_fdatasync_wrapper
 sys32_fdatasync_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_fdatasync		# branch to system call
 
-#sys32_sysctl_wrapper			# tbd 
+#sys32_sysctl_wrapper			# tbd
 
-	.globl  sys32_mlock_wrapper 
+	.globl	sys32_mlock_wrapper
 sys32_mlock_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	jg	sys_mlock		# branch to system call
 
-	.globl  sys32_munlock_wrapper 
+	.globl	sys32_munlock_wrapper
 sys32_munlock_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	jg	sys_munlock		# branch to system call
 
-	.globl  sys32_mlockall_wrapper 
+	.globl	sys32_mlockall_wrapper
 sys32_mlockall_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_mlockall		# branch to system call
 
-#sys32_munlockall_wrapper		# void 
+#sys32_munlockall_wrapper		# void
 
-	.globl  sys32_sched_setparam_wrapper 
+	.globl	sys32_sched_setparam_wrapper
 sys32_sched_setparam_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# struct sched_param *
 	jg	sys_sched_setparam	# branch to system call
 
-	.globl  sys32_sched_getparam_wrapper 
+	.globl	sys32_sched_getparam_wrapper
 sys32_sched_getparam_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# struct sched_param *
 	jg	sys_sched_getparam	# branch to system call
 
-	.globl  sys32_sched_setscheduler_wrapper 
+	.globl	sys32_sched_setscheduler_wrapper
 sys32_sched_setscheduler_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# struct sched_param *
 	jg	sys_sched_setscheduler	# branch to system call
 
-	.globl  sys32_sched_getscheduler_wrapper 
+	.globl	sys32_sched_getscheduler_wrapper
 sys32_sched_getscheduler_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	jg	sys_sched_getscheduler	# branch to system call
 
-#sys32_sched_yield_wrapper		# void 
+#sys32_sched_yield_wrapper		# void
 
-	.globl  sys32_sched_get_priority_max_wrapper 
+	.globl	sys32_sched_get_priority_max_wrapper
 sys32_sched_get_priority_max_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_sched_get_priority_max	# branch to system call
 
-	.globl  sys32_sched_get_priority_min_wrapper 
+	.globl	sys32_sched_get_priority_min_wrapper
 sys32_sched_get_priority_min_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_sched_get_priority_min	# branch to system call
 
-	.globl  sys32_sched_rr_get_interval_wrapper 
+	.globl	sys32_sched_rr_get_interval_wrapper
 sys32_sched_rr_get_interval_wrapper:
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# struct compat_timespec *
 	jg	sys32_sched_rr_get_interval	# branch to system call
 
-	.globl  compat_sys_nanosleep_wrapper 
+	.globl	compat_sys_nanosleep_wrapper
 compat_sys_nanosleep_wrapper:
 	llgtr	%r2,%r2			# struct compat_timespec *
 	llgtr	%r3,%r3			# struct compat_timespec *
 	jg	compat_sys_nanosleep		# branch to system call
 
-	.globl  sys32_mremap_wrapper 
+	.globl	sys32_mremap_wrapper
 sys32_mremap_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# unsigned long
@@ -769,49 +769,49 @@
 	llgfr	%r6,%r6			# unsigned long
 	jg	sys_mremap		# branch to system call
 
-	.globl  sys32_setresuid16_wrapper 
+	.globl	sys32_setresuid16_wrapper
 sys32_setresuid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
-	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
-	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
+	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t
 	jg	sys32_setresuid16	# branch to system call
 
-	.globl  sys32_getresuid16_wrapper 
+	.globl	sys32_getresuid16_wrapper
 sys32_getresuid16_wrapper:
 	llgtr	%r2,%r2			# __kernel_old_uid_emu31_t *
 	llgtr	%r3,%r3			# __kernel_old_uid_emu31_t *
 	llgtr	%r4,%r4			# __kernel_old_uid_emu31_t *
 	jg	sys32_getresuid16	# branch to system call
 
-	.globl  sys32_poll_wrapper 
+	.globl	sys32_poll_wrapper
 sys32_poll_wrapper:
-	llgtr	%r2,%r2			# struct pollfd * 
-	llgfr	%r3,%r3			# unsigned int 
-	lgfr	%r4,%r4			# long 
+	llgtr	%r2,%r2			# struct pollfd *
+	llgfr	%r3,%r3			# unsigned int
+	lgfr	%r4,%r4			# long
 	jg	sys_poll		# branch to system call
 
-	.globl  compat_sys_nfsservctl_wrapper
+	.globl	compat_sys_nfsservctl_wrapper
 compat_sys_nfsservctl_wrapper:
-	lgfr	%r2,%r2			# int 
+	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct compat_nfsctl_arg*
 	llgtr	%r4,%r4			# union compat_nfsctl_res*
 	jg	compat_sys_nfsservctl	# branch to system call
 
-	.globl  sys32_setresgid16_wrapper 
+	.globl	sys32_setresgid16_wrapper
 sys32_setresgid16_wrapper:
-	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
-	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t 
-	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t 
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
+	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t
+	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t
 	jg	sys32_setresgid16	# branch to system call
 
-	.globl  sys32_getresgid16_wrapper 
+	.globl	sys32_getresgid16_wrapper
 sys32_getresgid16_wrapper:
 	llgtr	%r2,%r2			# __kernel_old_gid_emu31_t *
 	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
 	llgtr	%r4,%r4			# __kernel_old_gid_emu31_t *
 	jg	sys32_getresgid16	# branch to system call
 
-	.globl  sys32_prctl_wrapper 
+	.globl	sys32_prctl_wrapper
 sys32_prctl_wrapper:
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# unsigned long
@@ -820,9 +820,9 @@
 	llgfr	%r6,%r6			# unsigned long
 	jg	sys_prctl		# branch to system call
 
-#sys32_rt_sigreturn_wrapper		# done in rt_sigreturn_glue 
+#sys32_rt_sigreturn_wrapper		# done in rt_sigreturn_glue
 
-	.globl  sys32_rt_sigaction_wrapper 
+	.globl	sys32_rt_sigaction_wrapper
 sys32_rt_sigaction_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct sigaction_emu31 *
@@ -830,7 +830,7 @@
 	llgfr	%r5,%r5			# size_t
 	jg	sys32_rt_sigaction	# branch to system call
 
-	.globl  sys32_rt_sigprocmask_wrapper 
+	.globl	sys32_rt_sigprocmask_wrapper
 sys32_rt_sigprocmask_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# old_sigset_emu31 *
@@ -838,13 +838,13 @@
 	llgfr	%r5,%r5			# size_t
 	jg	sys32_rt_sigprocmask	# branch to system call
 
-	.globl  sys32_rt_sigpending_wrapper 
+	.globl	sys32_rt_sigpending_wrapper
 sys32_rt_sigpending_wrapper:
 	llgtr	%r2,%r2			# sigset_emu31 *
 	llgfr	%r3,%r3			# size_t
 	jg	sys32_rt_sigpending	# branch to system call
 
-	.globl  compat_sys_rt_sigtimedwait_wrapper
+	.globl	compat_sys_rt_sigtimedwait_wrapper
 compat_sys_rt_sigtimedwait_wrapper:
 	llgtr	%r2,%r2			# const sigset_emu31_t *
 	llgtr	%r3,%r3			# siginfo_emu31_t *
@@ -852,7 +852,7 @@
 	llgfr	%r5,%r5			# size_t
 	jg	compat_sys_rt_sigtimedwait	# branch to system call
 
-	.globl  sys32_rt_sigqueueinfo_wrapper 
+	.globl	sys32_rt_sigqueueinfo_wrapper
 sys32_rt_sigqueueinfo_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
@@ -865,7 +865,7 @@
 	llgfr	%r3,%r3			# compat_size_t
 	jg	compat_sys_rt_sigsuspend
 
-	.globl  sys32_pread64_wrapper 
+	.globl	sys32_pread64_wrapper
 sys32_pread64_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# char *
@@ -874,7 +874,7 @@
 	llgfr	%r6,%r6			# u32
 	jg	sys32_pread64		# branch to system call
 
-	.globl  sys32_pwrite64_wrapper 
+	.globl	sys32_pwrite64_wrapper
 sys32_pwrite64_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# const char *
@@ -883,26 +883,26 @@
 	llgfr	%r6,%r6			# u32
 	jg	sys32_pwrite64		# branch to system call
 
-	.globl  sys32_chown16_wrapper 
+	.globl	sys32_chown16_wrapper
 sys32_chown16_wrapper:
 	llgtr	%r2,%r2			# const char *
-	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
-	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t 
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
+	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t
 	jg	sys32_chown16		# branch to system call
 
-	.globl  sys32_getcwd_wrapper 
+	.globl	sys32_getcwd_wrapper
 sys32_getcwd_wrapper:
 	llgtr	%r2,%r2			# char *
 	llgfr	%r3,%r3			# unsigned long
 	jg	sys_getcwd		# branch to system call
 
-	.globl  sys32_capget_wrapper 
+	.globl	sys32_capget_wrapper
 sys32_capget_wrapper:
 	llgtr	%r2,%r2			# cap_user_header_t
 	llgtr	%r3,%r3			# cap_user_data_t
 	jg	sys_capget		# branch to system call
 
-	.globl  sys32_capset_wrapper 
+	.globl	sys32_capset_wrapper
 sys32_capset_wrapper:
 	llgtr	%r2,%r2			# cap_user_header_t
 	llgtr	%r3,%r3			# const cap_user_data_t
@@ -910,11 +910,11 @@
 
 	.globl sys32_sigaltstack_wrapper
 sys32_sigaltstack_wrapper:
-	llgtr	%r2,%r2			# const stack_emu31_t * 
-	llgtr	%r3,%r3			# stack_emu31_t * 
+	llgtr	%r2,%r2			# const stack_emu31_t *
+	llgtr	%r3,%r3			# stack_emu31_t *
 	jg	sys32_sigaltstack
 
-	.globl  sys32_sendfile_wrapper 
+	.globl	sys32_sendfile_wrapper
 sys32_sendfile_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
@@ -922,33 +922,33 @@
 	llgfr	%r5,%r5			# size_t
 	jg	sys32_sendfile		# branch to system call
 
-#sys32_vfork_wrapper			# done in vfork_glue 
+#sys32_vfork_wrapper			# done in vfork_glue
 
-	.globl  sys32_truncate64_wrapper 
+	.globl	sys32_truncate64_wrapper
 sys32_truncate64_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys32_truncate64	# branch to system call
 
-	.globl  sys32_ftruncate64_wrapper 
+	.globl	sys32_ftruncate64_wrapper
 sys32_ftruncate64_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys32_ftruncate64	# branch to system call
 
-	.globl sys32_lchown_wrapper	
+	.globl sys32_lchown_wrapper
 sys32_lchown_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# gid_t
 	jg	sys_lchown		# branch to system call
 
-#sys32_getuid_wrapper			# void			 
-#sys32_getgid_wrapper			# void 
-#sys32_geteuid_wrapper			# void 
-#sys32_getegid_wrapper			# void 
+#sys32_getuid_wrapper			# void
+#sys32_getgid_wrapper			# void
+#sys32_geteuid_wrapper			# void
+#sys32_getegid_wrapper			# void
 
 	.globl sys32_setreuid_wrapper
 sys32_setreuid_wrapper:
@@ -962,111 +962,111 @@
 	llgfr	%r3,%r3			# gid_t
 	jg	sys_setregid		# branch to system call
 
-	.globl  sys32_getgroups_wrapper 
+	.globl	sys32_getgroups_wrapper
 sys32_getgroups_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# gid_t *
 	jg	sys_getgroups		# branch to system call
 
-	.globl  sys32_setgroups_wrapper 
+	.globl	sys32_setgroups_wrapper
 sys32_setgroups_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# gid_t *
 	jg	sys_setgroups		# branch to system call
 
-	.globl sys32_fchown_wrapper	
+	.globl sys32_fchown_wrapper
 sys32_fchown_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# gid_t
 	jg	sys_fchown		# branch to system call
 
-	.globl sys32_setresuid_wrapper	
+	.globl sys32_setresuid_wrapper
 sys32_setresuid_wrapper:
 	llgfr	%r2,%r2			# uid_t
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# uid_t
 	jg	sys_setresuid		# branch to system call
 
-	.globl sys32_getresuid_wrapper	
+	.globl sys32_getresuid_wrapper
 sys32_getresuid_wrapper:
 	llgtr	%r2,%r2			# uid_t *
 	llgtr	%r3,%r3			# uid_t *
 	llgtr	%r4,%r4			# uid_t *
 	jg	sys_getresuid		# branch to system call
 
-	.globl sys32_setresgid_wrapper	
+	.globl sys32_setresgid_wrapper
 sys32_setresgid_wrapper:
 	llgfr	%r2,%r2			# gid_t
 	llgfr	%r3,%r3			# gid_t
 	llgfr	%r4,%r4			# gid_t
 	jg	sys_setresgid		# branch to system call
 
-	.globl sys32_getresgid_wrapper	
+	.globl sys32_getresgid_wrapper
 sys32_getresgid_wrapper:
 	llgtr	%r2,%r2			# gid_t *
 	llgtr	%r3,%r3			# gid_t *
 	llgtr	%r4,%r4			# gid_t *
 	jg	sys_getresgid		# branch to system call
 
-	.globl sys32_chown_wrapper	
+	.globl sys32_chown_wrapper
 sys32_chown_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# gid_t
 	jg	sys_chown		# branch to system call
 
-	.globl sys32_setuid_wrapper	
+	.globl sys32_setuid_wrapper
 sys32_setuid_wrapper:
 	llgfr	%r2,%r2			# uid_t
 	jg	sys_setuid		# branch to system call
 
-	.globl sys32_setgid_wrapper	
+	.globl sys32_setgid_wrapper
 sys32_setgid_wrapper:
 	llgfr	%r2,%r2			# gid_t
 	jg	sys_setgid		# branch to system call
 
-	.globl sys32_setfsuid_wrapper	
+	.globl sys32_setfsuid_wrapper
 sys32_setfsuid_wrapper:
 	llgfr	%r2,%r2			# uid_t
 	jg	sys_setfsuid		# branch to system call
 
-	.globl sys32_setfsgid_wrapper	
+	.globl sys32_setfsgid_wrapper
 sys32_setfsgid_wrapper:
 	llgfr	%r2,%r2			# gid_t
 	jg	sys_setfsgid		# branch to system call
 
-	.globl  sys32_pivot_root_wrapper 
+	.globl	sys32_pivot_root_wrapper
 sys32_pivot_root_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_pivot_root		# branch to system call
 
-	.globl  sys32_mincore_wrapper 
+	.globl	sys32_mincore_wrapper
 sys32_mincore_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	llgtr	%r4,%r4			# unsigned char *
 	jg	sys_mincore		# branch to system call
 
-	.globl  sys32_madvise_wrapper 
+	.globl	sys32_madvise_wrapper
 sys32_madvise_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	lgfr	%r4,%r4			# int
 	jg	sys_madvise		# branch to system call
 
-	.globl  sys32_getdents64_wrapper 
+	.globl	sys32_getdents64_wrapper
 sys32_getdents64_wrapper:
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# void *
 	llgfr	%r4,%r4			# unsigned int
 	jg	sys_getdents64		# branch to system call
 
-	.globl  compat_sys_fcntl64_wrapper 
+	.globl	compat_sys_fcntl64_wrapper
 compat_sys_fcntl64_wrapper:
 	llgfr	%r2,%r2			# unsigned int
-	llgfr	%r3,%r3			# unsigned int 
+	llgfr	%r3,%r3			# unsigned int
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_fcntl64	# branch to system call
 
@@ -1087,10 +1087,10 @@
 	llgtr	%r2,%r2			# long *
 	jg	compat_sys_stime	# branch to system call
 
-	.globl  sys32_sysctl_wrapper
+	.globl	sys32_sysctl_wrapper
 sys32_sysctl_wrapper:
-	llgtr   %r2,%r2                 # struct __sysctl_args32 *
-	jg      sys32_sysctl
+	llgtr	%r2,%r2 		# struct __sysctl_args32 *
+	jg	sys32_sysctl
 
 	.globl	sys32_fstat64_wrapper
 sys32_fstat64_wrapper:
@@ -1098,7 +1098,7 @@
 	llgtr	%r3,%r3			# struct stat64 *
 	jg	sys32_fstat64		# branch to system call
 
-	.globl  compat_sys_futex_wrapper 
+	.globl	compat_sys_futex_wrapper
 compat_sys_futex_wrapper:
 	llgtr	%r2,%r2			# u32 *
 	lgfr	%r3,%r3			# int
@@ -1213,22 +1213,22 @@
 	llgtr	%r4,%r4			# unsigned long *
 	jg	compat_sys_sched_getaffinity
 
-	.globl  sys32_exit_group_wrapper
+	.globl	sys32_exit_group_wrapper
 sys32_exit_group_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_exit_group		# branch to system call
 
-	.globl  sys32_set_tid_address_wrapper
+	.globl	sys32_set_tid_address_wrapper
 sys32_set_tid_address_wrapper:
 	llgtr	%r2,%r2			# int *
 	jg	sys_set_tid_address	# branch to system call
 
-	.globl  sys_epoll_create_wrapper
+	.globl	sys_epoll_create_wrapper
 sys_epoll_create_wrapper:
 	lgfr	%r2,%r2			# int
 	jg	sys_epoll_create	# branch to system call
 
-	.globl  sys_epoll_ctl_wrapper
+	.globl	sys_epoll_ctl_wrapper
 sys_epoll_ctl_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
@@ -1236,7 +1236,7 @@
 	llgtr	%r5,%r5			# struct epoll_event *
 	jg	sys_epoll_ctl		# branch to system call
 
-	.globl  sys_epoll_wait_wrapper
+	.globl	sys_epoll_wait_wrapper
 sys_epoll_wait_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct epoll_event *
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 4ef44e5..1eae74e 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -25,11 +25,8 @@
  */
 int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 {
-	const int mask = 0x40000000L;
-	unsigned long flags;
-	int return_code;
-	int return_len;
-	int cmdlen;
+	unsigned long flags, cmdlen;
+	int return_code, return_len;
 
 	spin_lock_irqsave(&cpcmd_lock, flags);
 	cmdlen = strlen(cmd);
@@ -38,64 +35,44 @@
 	ASCEBC(cpcmd_buf, cmdlen);
 
 	if (response != NULL && rlen > 0) {
+		register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+		register unsigned long reg3 asm ("3") = (addr_t) response;
+		register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
+		register unsigned long reg5 asm ("5") = rlen;
+
 		memset(response, 0, rlen);
+		asm volatile(
 #ifndef CONFIG_64BIT
-		asm volatile (	"lra	2,0(%2)\n"
-				"lr	4,%3\n"
-				"o	4,%6\n"
-				"lra	3,0(%4)\n"
-				"lr	5,%5\n"
-				"diag	2,4,0x8\n"
-				"brc	8, 1f\n"
-				"ar	5, %5\n"
-				"1: \n"
-				"lr	%0,4\n"
-				"lr	%1,5\n"
-				: "=d" (return_code), "=d" (return_len)
-				: "a" (cpcmd_buf), "d" (cmdlen),
-				"a" (response), "d" (rlen), "m" (mask)
-				: "cc", "2", "3", "4", "5" );
+			"	diag	%2,%0,0x8\n"
+			"	brc	8,1f\n"
+			"	ar	%1,%4\n"
 #else /* CONFIG_64BIT */
-                asm volatile (	"lrag	2,0(%2)\n"
-				"lgr	4,%3\n"
-				"o	4,%6\n"
-				"lrag	3,0(%4)\n"
-				"lgr	5,%5\n"
-				"sam31\n"
-				"diag	2,4,0x8\n"
-				"sam64\n"
-				"brc	8, 1f\n"
-				"agr	5, %5\n"
-				"1: \n"
-				"lgr	%0,4\n"
-				"lgr	%1,5\n"
-				: "=d" (return_code), "=d" (return_len)
-				: "a" (cpcmd_buf), "d" (cmdlen),
-				"a" (response), "d" (rlen), "m" (mask)
-				: "cc", "2", "3", "4", "5" );
+			"	sam31\n"
+			"	diag	%2,%0,0x8\n"
+			"	sam64\n"
+			"	brc	8,1f\n"
+			"	agr	%1,%4\n"
 #endif /* CONFIG_64BIT */
+			"1:\n"
+			: "+d" (reg4), "+d" (reg5)
+			: "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
+		return_code = (int) reg4;
+		return_len = (int) reg5;
                 EBCASC(response, rlen);
         } else {
+		register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+		register unsigned long reg3 asm ("3") = cmdlen;
 		return_len = 0;
+		asm volatile(
 #ifndef CONFIG_64BIT
-                asm volatile (	"lra	2,0(%1)\n"
-				"lr	3,%2\n"
-				"diag	2,3,0x8\n"
-				"lr	%0,3\n"
-				: "=d" (return_code)
-				: "a" (cpcmd_buf), "d" (cmdlen)
-				: "2", "3"  );
+			"	diag	%1,%0,0x8\n"
 #else /* CONFIG_64BIT */
-                asm volatile (	"lrag	2,0(%1)\n"
-				"lgr	3,%2\n"
-				"sam31\n"
-				"diag	2,3,0x8\n"
-				"sam64\n"
-				"lgr	%0,3\n"
-				: "=d" (return_code)
-				: "a" (cpcmd_buf), "d" (cmdlen)
-				: "2", "3" );
+			"	sam31\n"
+			"	diag	%1,%0,0x8\n"
+			"	sam64\n"
 #endif /* CONFIG_64BIT */
+			: "+d" (reg3) : "d" (reg2) : "cc");
+		return_code = (int) reg3;
         }
 	spin_unlock_irqrestore(&cpcmd_lock, flags);
 	if (response_code != NULL)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 0c712b7..dddc3de 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -4,8 +4,8 @@
  *
  *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *               Hartmut Penner (hp@de.ibm.com),
- *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *		 Hartmut Penner (hp@de.ibm.com),
+ *		 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
@@ -24,29 +24,29 @@
  * Stack layout for the system_call stack entry.
  * The first few entries are identical to the user_regs_struct.
  */
-SP_PTREGS    =  STACK_FRAME_OVERHEAD
-SP_ARGS      =  STACK_FRAME_OVERHEAD + __PT_ARGS
-SP_PSW       =  STACK_FRAME_OVERHEAD + __PT_PSW
-SP_R0        =  STACK_FRAME_OVERHEAD + __PT_GPRS
-SP_R1        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 4
-SP_R2        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 8
-SP_R3        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 12
-SP_R4        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 16
-SP_R5        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 20
-SP_R6        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 24
-SP_R7        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 28
-SP_R8        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 32
-SP_R9        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 36
-SP_R10       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 40
-SP_R11       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 44
-SP_R12       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 48
-SP_R13       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 52
-SP_R14       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 56
-SP_R15       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 60
-SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC       =  STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
-SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
+SP_PTREGS    =	STACK_FRAME_OVERHEAD
+SP_ARGS      =	STACK_FRAME_OVERHEAD + __PT_ARGS
+SP_PSW	     =	STACK_FRAME_OVERHEAD + __PT_PSW
+SP_R0	     =	STACK_FRAME_OVERHEAD + __PT_GPRS
+SP_R1	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 4
+SP_R2	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 8
+SP_R3	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 12
+SP_R4	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 16
+SP_R5	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 20
+SP_R6	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 24
+SP_R7	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 28
+SP_R8	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 32
+SP_R9	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 36
+SP_R10	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 40
+SP_R11	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 44
+SP_R12	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 48
+SP_R13	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 52
+SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 56
+SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 60
+SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
+SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
+SP_TRAP      =	STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
@@ -81,14 +81,14 @@
  *    R15 - kernel stack pointer
  */
 
-	.macro  STORE_TIMER lc_offset
+	.macro	STORE_TIMER lc_offset
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	stpt	\lc_offset
 #endif
 	.endm
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	.macro  UPDATE_VTIME lc_from,lc_to,lc_sum
+	.macro	UPDATE_VTIME lc_from,lc_to,lc_sum
 	lm	%r10,%r11,\lc_from
 	sl	%r10,\lc_to
 	sl	%r11,\lc_to+4
@@ -147,7 +147,7 @@
 2:
 	.endm
 
-	.macro  CREATE_STACK_FRAME psworg,savearea
+	.macro	CREATE_STACK_FRAME psworg,savearea
 	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
@@ -160,7 +160,7 @@
 	st	%r12,__SF_BACKCHAIN(%r15)	# clear back chain
 	.endm
 
-	.macro  RESTORE_ALL psworg,sync
+	.macro	RESTORE_ALL psworg,sync
 	mvc	\psworg(8),SP_PSW(%r15) # move user PSW to lowcore
 	.if !\sync
 	ni	\psworg+1,0xfd		# clear wait state bit
@@ -177,16 +177,16 @@
  * Returns:
  *  gpr2 = prev
  */
-        .globl  __switch_to
+	.globl	__switch_to
 __switch_to:
-        basr    %r1,0
+	basr	%r1,0
 __switch_to_base:
 	tm	__THREAD_per(%r3),0xe8		# new process is using per ?
 	bz	__switch_to_noper-__switch_to_base(%r1)	# if not we're fine
-        stctl   %c9,%c11,__SF_EMPTY(%r15)	# We are using per stuff
-        clc     __THREAD_per(12,%r3),__SF_EMPTY(%r15)
-        be      __switch_to_noper-__switch_to_base(%r1)	# we got away w/o bashing TLB's
-        lctl    %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
+	stctl	%c9,%c11,__SF_EMPTY(%r15)	# We are using per stuff
+	clc	__THREAD_per(12,%r3),__SF_EMPTY(%r15)
+	be	__switch_to_noper-__switch_to_base(%r1)	# we got away w/o bashing TLB's
+	lctl	%c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
 	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
 	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
@@ -195,13 +195,13 @@
 	l	%r4,__THREAD_info(%r3)		# get thread_info of next
 	oi	__TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
 __switch_to_no_mcck:
-        stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
+	stm	%r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	st	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	l	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
 	lm	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	st	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
 	lctl	%c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
-	l	%r3,__THREAD_info(%r3)  # load thread_info from task struct
+	l	%r3,__THREAD_info(%r3)	# load thread_info from task struct
 	st	%r3,__LC_THREAD_INFO
 	ahi	%r3,STACK_SIZE
 	st	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
@@ -213,7 +213,7 @@
  * are executed with interrupts enabled.
  */
 
-	.globl  system_call
+	.globl	system_call
 system_call:
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
@@ -233,24 +233,24 @@
 #endif
 sysc_do_svc:
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-	sla	%r7,2             # *4 and test for svc 0
-	bnz	BASED(sysc_nr_ok) # svc number > 0
+	sla	%r7,2			# *4 and test for svc 0
+	bnz	BASED(sysc_nr_ok)	# svc number > 0
 	# svc 0: system call number in %r1
 	cl	%r1,BASED(.Lnr_syscalls)
 	bnl	BASED(sysc_nr_ok)
-	lr	%r7,%r1           # copy svc number to %r7
-	sla	%r7,2             # *4
+	lr	%r7,%r1 	  # copy svc number to %r7
+	sla	%r7,2		  # *4
 sysc_nr_ok:
 	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
 sysc_do_restart:
 	l	%r8,BASED(.Lsysc_table)
 	tm	__TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
 	l	%r8,0(%r7,%r8)	  # get system call addr.
-        bnz     BASED(sysc_tracesys)
-        basr    %r14,%r8          # call sys_xxxx
-        st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
-                                  # ATTENTION: check sys_execve_glue before
-                                  # changing anything here !!
+	bnz	BASED(sysc_tracesys)
+	basr	%r14,%r8	  # call sys_xxxx
+	st	%r2,SP_R2(%r15)   # store return value (change R2 on stack)
+				  # ATTENTION: check sys_execve_glue before
+				  # changing anything here !!
 
 sysc_return:
 	tm	SP_PSW+1(%r15),0x01	# returning to user ?
@@ -258,14 +258,14 @@
 	tm	__TI_flags+3(%r9),_TIF_WORK_SVC
 	bnz	BASED(sysc_work)  # there is work to do (signals etc.)
 sysc_leave:
-        RESTORE_ALL __LC_RETURN_PSW,1
+	RESTORE_ALL __LC_RETURN_PSW,1
 
 #
 # recheck if there is more work to do
 #
 sysc_work_loop:
 	tm	__TI_flags+3(%r9),_TIF_WORK_SVC
-	bz	BASED(sysc_leave)      # there is no work to do
+	bz	BASED(sysc_leave)	# there is no work to do
 #
 # One of the work bits is on. Find out which one.
 #
@@ -284,11 +284,11 @@
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#	
-sysc_reschedule:        
-        l       %r1,BASED(.Lschedule)
-	la      %r14,BASED(sysc_work_loop)
-	br      %r1		       # call scheduler
+#
+sysc_reschedule:
+	l	%r1,BASED(.Lschedule)
+	la	%r14,BASED(sysc_work_loop)
+	br	%r1			# call scheduler
 
 #
 # _TIF_MCCK_PENDING is set, call handler
@@ -301,11 +301,11 @@
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-sysc_sigpending:     
+sysc_sigpending:
 	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Ldo_signal)
-	basr	%r14,%r1               # call do_signal
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	l	%r1,BASED(.Ldo_signal)
+	basr	%r14,%r1		# call do_signal
 	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
 	bo	BASED(sysc_restart)
 	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
@@ -317,11 +317,11 @@
 #
 sysc_restart:
 	ni	__TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-	l	%r7,SP_R2(%r15)        # load new svc number
+	l	%r7,SP_R2(%r15) 	# load new svc number
 	sla	%r7,2
 	mvc	SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
-	lm	%r2,%r6,SP_R2(%r15)    # load svc arguments
-	b	BASED(sysc_do_restart) # restart svc
+	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
+	b	BASED(sysc_do_restart)	# restart svc
 
 #
 # _TIF_SINGLE_STEP is set, call do_single_step
@@ -338,8 +338,8 @@
 # call trace before and after sys_call
 #
 sysc_tracesys:
-        l       %r1,BASED(.Ltrace)
-	la	%r2,SP_PTREGS(%r15)    # load pt_regs
+	l	%r1,BASED(.Ltrace)
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,0
 	srl	%r7,2
 	st	%r7,SP_R2(%r15)
@@ -347,19 +347,19 @@
 	clc	SP_R2(4,%r15),BASED(.Lnr_syscalls)
 	bnl	BASED(sysc_tracenogo)
 	l	%r8,BASED(.Lsysc_table)
-	l	%r7,SP_R2(%r15)        # strace might have changed the 
-	sll	%r7,2                  #  system call
+	l	%r7,SP_R2(%r15) 	# strace might have changed the
+	sll	%r7,2			#  system call
 	l	%r8,0(%r7,%r8)
 sysc_tracego:
 	lm	%r3,%r6,SP_R3(%r15)
 	l	%r2,SP_ORIG_R2(%r15)
-	basr	%r14,%r8          # call sys_xxx
-	st	%r2,SP_R2(%r15)   # store return value
+	basr	%r14,%r8		# call sys_xxx
+	st	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
 	tm	__TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
-        bz      BASED(sysc_return)
+	bz	BASED(sysc_return)
 	l	%r1,BASED(.Ltrace)
-	la	%r2,SP_PTREGS(%r15)    # load pt_regs
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,1
 	la	%r14,BASED(sysc_return)
 	br	%r1
@@ -367,17 +367,17 @@
 #
 # a new process exits the kernel with ret_from_fork
 #
-        .globl  ret_from_fork
+	.globl	ret_from_fork
 ret_from_fork:
 	l	%r13,__LC_SVC_NEW_PSW+4
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
 	bo	BASED(0f)
 	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
-0:	l       %r1,BASED(.Lschedtail)
-	basr    %r14,%r1
+0:	l	%r1,BASED(.Lschedtail)
+	basr	%r14,%r1
 	TRACE_IRQS_ON
-        stosm   __SF_EMPTY(%r15),0x03     # reenable interrupts
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	b	BASED(sysc_return)
 
 #
@@ -386,52 +386,51 @@
 # but are called with different parameter.
 # return-address is set up above
 #
-sys_clone_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Lclone)
-        br      %r1                   # branch to sys_clone
+sys_clone_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	l	%r1,BASED(.Lclone)
+	br	%r1			# branch to sys_clone
 
-sys_fork_glue:  
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Lfork)
-        br      %r1                   # branch to sys_fork
+sys_fork_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	l	%r1,BASED(.Lfork)
+	br	%r1			# branch to sys_fork
 
-sys_vfork_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Lvfork)
-        br      %r1                   # branch to sys_vfork
+sys_vfork_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	l	%r1,BASED(.Lvfork)
+	br	%r1			# branch to sys_vfork
 
-sys_execve_glue:        
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs
-        l       %r1,BASED(.Lexecve)
-	lr      %r12,%r14             # save return address
-        basr    %r14,%r1              # call sys_execve
-        ltr     %r2,%r2               # check if execve failed
-        bnz     0(%r12)               # it did fail -> store result in gpr2
-        b       4(%r12)               # SKIP ST 2,SP_R2(15) after BASR 14,8
-                                      # in system_call/sysc_tracesys
+sys_execve_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	l	%r1,BASED(.Lexecve)
+	lr	%r12,%r14		# save return address
+	basr	%r14,%r1		# call sys_execve
+	ltr	%r2,%r2			# check if execve failed
+	bnz	0(%r12)			# it did fail -> store result in gpr2
+	b	4(%r12)			# SKIP ST 2,SP_R2(15) after BASR 14,8
+					# in system_call/sysc_tracesys
 
-sys_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,BASED(.Lsigreturn)
-        br      %r1                   # branch to sys_sigreturn
+sys_sigreturn_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs as parameter
+	l	%r1,BASED(.Lsigreturn)
+	br	%r1			# branch to sys_sigreturn
 
-sys_rt_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,BASED(.Lrt_sigreturn)
-        br      %r1                   # branch to sys_sigreturn
+sys_rt_sigreturn_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs as parameter
+	l	%r1,BASED(.Lrt_sigreturn)
+	br	%r1			# branch to sys_sigreturn
 
 sys_sigaltstack_glue:
-        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,BASED(.Lsigaltstack)
-        br      %r1                   # branch to sys_sigreturn
-
+	la	%r4,SP_PTREGS(%r15)	# load pt_regs as parameter
+	l	%r1,BASED(.Lsigaltstack)
+	br	%r1			# branch to sys_sigreturn
 
 /*
  * Program check handler routine
  */
 
-        .globl  pgm_check_handler
+	.globl	pgm_check_handler
 pgm_check_handler:
 /*
  * First we need to check for a special case:
@@ -448,8 +447,8 @@
  */
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 	SAVE_ALL_BASE __LC_SAVE_AREA
-        tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
-        bnz     BASED(pgm_per)           # got per exception -> special case
+	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+	bnz	BASED(pgm_per)		# got per exception -> special case
 	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -461,29 +460,29 @@
 pgm_no_vtime:
 #endif
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        l       %r3,__LC_PGM_ILC         # load program interruption code
+	l	%r3,__LC_PGM_ILC	# load program interruption code
 	la	%r8,0x7f
 	nr	%r8,%r3
 pgm_do_call:
-        l       %r7,BASED(.Ljump_table)
-        sll     %r8,2
-        l       %r7,0(%r8,%r7)		 # load address of handler routine
-        la      %r2,SP_PTREGS(%r15)	 # address of register-save area
-	la      %r14,BASED(sysc_return)
-	br      %r7			 # branch to interrupt-handler
+	l	%r7,BASED(.Ljump_table)
+	sll	%r8,2
+	l	%r7,0(%r8,%r7)		# load address of handler routine
+	la	%r2,SP_PTREGS(%r15)	# address of register-save area
+	la	%r14,BASED(sysc_return)
+	br	%r7			# branch to interrupt-handler
 
 #
 # handle per exception
 #
 pgm_per:
-        tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
-        bnz     BASED(pgm_per_std)       # ok, normal per event from user space
+	tm	__LC_PGM_OLD_PSW,0x40	# test if per event recording is on
+	bnz	BASED(pgm_per_std)	# ok, normal per event from user space
 # ok its one of the special cases, now we need to find out which one
-        clc     __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
-        be      BASED(pgm_svcper)
+	clc	__LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
+	be	BASED(pgm_svcper)
 # no interesting special case, ignore PER event
-        lm      %r12,%r15,__LC_SAVE_AREA
-	lpsw    0x28
+	lm	%r12,%r15,__LC_SAVE_AREA
+	lpsw	0x28
 
 #
 # Normal per exception
@@ -507,10 +506,10 @@
 	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
 	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
 	bz	BASED(kernel_per)
-	l	%r3,__LC_PGM_ILC	 # load program interruption code
+	l	%r3,__LC_PGM_ILC	# load program interruption code
 	la	%r8,0x7f
-	nr	%r8,%r3                  # clear per-event-bit and ilc
-	be	BASED(sysc_return)       # only per or per+check ?
+	nr	%r8,%r3 		# clear per-event-bit and ilc
+	be	BASED(sysc_return)	# only per or per+check ?
 	b	BASED(pgm_do_call)
 
 #
@@ -552,7 +551,7 @@
  * IO interrupt handler routine
  */
 
-        .globl io_int_handler
+	.globl io_int_handler
 io_int_handler:
 	STORE_TIMER __LC_ASYNC_ENTER_TIMER
 	stck	__LC_INT_CLOCK
@@ -569,42 +568,42 @@
 #endif
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	TRACE_IRQS_OFF
-        l       %r1,BASED(.Ldo_IRQ)        # load address of do_IRQ
-        la      %r2,SP_PTREGS(%r15) # address of register-save area
-        basr    %r14,%r1          # branch to standard irq handler
+	l	%r1,BASED(.Ldo_IRQ)	# load address of do_IRQ
+	la	%r2,SP_PTREGS(%r15)	# address of register-save area
+	basr	%r14,%r1		# branch to standard irq handler
 	TRACE_IRQS_ON
 
 io_return:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
 #ifdef CONFIG_PREEMPT
-	bno     BASED(io_preempt)      # no -> check for preemptive scheduling
+	bno	BASED(io_preempt)	# no -> check for preemptive scheduling
 #else
-        bno     BASED(io_leave)        # no-> skip resched & signal
+	bno	BASED(io_leave) 	# no-> skip resched & signal
 #endif
 	tm	__TI_flags+3(%r9),_TIF_WORK_INT
-	bnz	BASED(io_work)         # there is work to do (signals etc.)
+	bnz	BASED(io_work)		# there is work to do (signals etc.)
 io_leave:
-        RESTORE_ALL __LC_RETURN_PSW,0
+	RESTORE_ALL __LC_RETURN_PSW,0
 io_done:
 
 #ifdef CONFIG_PREEMPT
 io_preempt:
 	icm	%r0,15,__TI_precount(%r9)
-	bnz     BASED(io_leave)
+	bnz	BASED(io_leave)
 	l	%r1,SP_R15(%r15)
 	s	%r1,BASED(.Lc_spsize)
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 io_resume_loop:
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bno	BASED(io_leave)
-	mvc     __TI_precount(4,%r9),BASED(.Lc_pactive)
-        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
-        l       %r1,BASED(.Lschedule)
+	mvc	__TI_precount(4,%r9),BASED(.Lc_pactive)
+	stosm	__SF_EMPTY(%r15),0x03  # reenable interrupts
+	l	%r1,BASED(.Lschedule)
 	basr	%r14,%r1	       # call schedule
-        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
-	xc      __TI_precount(4,%r9),__TI_precount(%r9)
+	stnsm	__SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
+	xc	__TI_precount(4,%r9),__TI_precount(%r9)
 	b	BASED(io_resume_loop)
 #endif
 
@@ -615,16 +614,16 @@
 	l	%r1,__LC_KERNEL_STACK
 	s	%r1,BASED(.Lc_spsize)
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
 # Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
-#	        and _TIF_MCCK_PENDING
+#		and _TIF_MCCK_PENDING
 #
 io_work_loop:
 	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
-	bo      BASED(io_mcck_pending)
+	bo	BASED(io_mcck_pending)
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bo	BASED(io_reschedule)
 	tm	__TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
@@ -637,36 +636,36 @@
 io_mcck_pending:
 	l	%r1,BASED(.Ls390_handle_mcck)
 	la	%r14,BASED(io_work_loop)
-	br	%r1		       # TIF bit will be cleared by handler
+	br	%r1			# TIF bit will be cleared by handler
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#	
-io_reschedule:        
-        l       %r1,BASED(.Lschedule)
-        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
-	basr    %r14,%r1	       # call scheduler
-        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
+#
+io_reschedule:
+	l	%r1,BASED(.Lschedule)
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
+	basr	%r14,%r1		# call scheduler
+	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
 	tm	__TI_flags+3(%r9),_TIF_WORK_INT
-	bz	BASED(io_leave)        # there is no work to do
+	bz	BASED(io_leave) 	# there is no work to do
 	b	BASED(io_work_loop)
 
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-io_sigpending:     
-        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Ldo_signal)
-	basr    %r14,%r1	       # call do_signal
-        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
+io_sigpending:
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	l	%r1,BASED(.Ldo_signal)
+	basr	%r14,%r1		# call do_signal
+	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
 	b	BASED(io_work_loop)
 
 /*
  * External interrupt handler routine
  */
 
-        .globl  ext_int_handler
+	.globl	ext_int_handler
 ext_int_handler:
 	STORE_TIMER __LC_ASYNC_ENTER_TIMER
 	stck	__LC_INT_CLOCK
@@ -683,8 +682,8 @@
 #endif
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	TRACE_IRQS_OFF
-	la	%r2,SP_PTREGS(%r15)    # address of register-save area
-	lh	%r3,__LC_EXT_INT_CODE  # get interruption code
+	la	%r2,SP_PTREGS(%r15)	# address of register-save area
+	lh	%r3,__LC_EXT_INT_CODE	# get interruption code
 	l	%r1,BASED(.Ldo_extint)
 	basr	%r14,%r1
 	TRACE_IRQS_ON
@@ -696,13 +695,13 @@
  * Machine check handler routines
  */
 
-        .globl mcck_int_handler
+	.globl mcck_int_handler
 mcck_int_handler:
 	spt	__LC_CPU_TIMER_SAVE_AREA	# revalidate cpu timer
 	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA	# revalidate gprs
 	SAVE_ALL_BASE __LC_SAVE_AREA+32
 	la	%r12,__LC_MCK_OLD_PSW
-	tm	__LC_MCCK_CODE,0x80     # system damage?
+	tm	__LC_MCCK_CODE,0x80	# system damage?
 	bo	BASED(mcck_int_main)	# yes -> rest of mcck code invalid
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	mvc	__LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER
@@ -741,7 +740,7 @@
 	l	%r15,__LC_PANIC_STACK	# load panic stack
 0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	tm	__LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
+	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
 	bno	BASED(mcck_no_vtime)	# no -> skip cleanup critical
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(mcck_no_vtime)
@@ -752,14 +751,14 @@
 #endif
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
-	l       %r1,BASED(.Ls390_mcck)
-	basr    %r14,%r1		# call machine check handler
-	tm      SP_PSW+1(%r15),0x01	# returning to user ?
+	l	%r1,BASED(.Ls390_mcck)
+	basr	%r14,%r1		# call machine check handler
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
 	bno	BASED(mcck_return)
-	l	%r1,__LC_KERNEL_STACK   # switch to kernel stack
+	l	%r1,__LC_KERNEL_STACK	# switch to kernel stack
 	s	%r1,BASED(.Lc_spsize)
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-	xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
 	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
@@ -783,36 +782,36 @@
 	lm	%r0,%r15,SP_R0(%r15)	# load gprs 0-15
 	lpsw	__LC_RETURN_MCCK_PSW	# back to caller
 
-        RESTORE_ALL __LC_RETURN_MCCK_PSW,0
+	RESTORE_ALL __LC_RETURN_MCCK_PSW,0
 
 #ifdef CONFIG_SMP
 /*
  * Restart interruption handler, kick starter for additional CPUs
  */
-        .globl restart_int_handler
+	.globl restart_int_handler
 restart_int_handler:
-        l       %r15,__LC_SAVE_AREA+60 # load ksp
-        lctl    %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
-        lam     %a0,%a15,__LC_AREGS_SAVE_AREA
-        lm      %r6,%r15,__SF_GPRS(%r15) # load registers from clone
-        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
-        basr    %r14,0
-        l       %r14,restart_addr-.(%r14)
-        br      %r14                   # branch to start_secondary
+	l	%r15,__LC_SAVE_AREA+60	# load ksp
+	lctl	%c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
+	lam	%a0,%a15,__LC_AREGS_SAVE_AREA
+	lm	%r6,%r15,__SF_GPRS(%r15) # load registers from clone
+	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
+	basr	%r14,0
+	l	%r14,restart_addr-.(%r14)
+	br	%r14			# branch to start_secondary
 restart_addr:
-        .long   start_secondary
+	.long	start_secondary
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-        .globl restart_int_handler
+	.globl restart_int_handler
 restart_int_handler:
-        basr    %r1,0
+	basr	%r1,0
 restart_base:
-        lpsw    restart_crash-restart_base(%r1)
-        .align 8
+	lpsw	restart_crash-restart_base(%r1)
+	.align	8
 restart_crash:
-        .long  0x000a0000,0x00000000
+	.long	0x000a0000,0x00000000
 restart_go:
 #endif
 
@@ -834,11 +833,11 @@
 	be	BASED(0f)
 	la	%r1,__LC_SAVE_AREA+16
 0:	mvc	SP_R12(16,%r15),0(%r1)	# move %r12-%r15 to stack
-        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
 	l	%r1,BASED(1f)		# branch to kernel_stack_overflow
-        la      %r2,SP_PTREGS(%r15)	# load pt_regs
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	br	%r1
-1:	.long  kernel_stack_overflow
+1:	.long	kernel_stack_overflow
 #endif
 
 cleanup_table_system_call:
@@ -940,10 +939,10 @@
 cleanup_system_call_insn:
 	.long	sysc_saveall + 0x80000000
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	.long   system_call + 0x80000000
-	.long   sysc_vtime + 0x80000000
-	.long   sysc_stime + 0x80000000
-	.long   sysc_update + 0x80000000
+	.long	system_call + 0x80000000
+	.long	sysc_vtime + 0x80000000
+	.long	sysc_stime + 0x80000000
+	.long	sysc_update + 0x80000000
 #endif
 
 cleanup_sysc_return:
@@ -1009,57 +1008,57 @@
 /*
  * Integer constants
  */
-               .align 4
-.Lc_spsize:    .long  SP_SIZE
-.Lc_overhead:  .long  STACK_FRAME_OVERHEAD
-.Lc_pactive:   .long  PREEMPT_ACTIVE
-.Lnr_syscalls: .long  NR_syscalls
-.L0x018:       .short 0x018
-.L0x020:       .short 0x020
-.L0x028:       .short 0x028
-.L0x030:       .short 0x030
-.L0x038:       .short 0x038
-.Lc_1:         .long  1
+		.align	4
+.Lc_spsize:	.long	SP_SIZE
+.Lc_overhead:	.long	STACK_FRAME_OVERHEAD
+.Lc_pactive:	.long	PREEMPT_ACTIVE
+.Lnr_syscalls:	.long	NR_syscalls
+.L0x018:	.short	0x018
+.L0x020:	.short	0x020
+.L0x028:	.short	0x028
+.L0x030:	.short	0x030
+.L0x038:	.short	0x038
+.Lc_1:		.long	1
 
 /*
  * Symbol constants
  */
-.Ls390_mcck:   .long  s390_do_machine_check
+.Ls390_mcck:	.long	s390_do_machine_check
 .Ls390_handle_mcck:
-	       .long  s390_handle_mcck
-.Lmck_old_psw: .long  __LC_MCK_OLD_PSW
-.Ldo_IRQ:      .long  do_IRQ
-.Ldo_extint:   .long  do_extint
-.Ldo_signal:   .long  do_signal
-.Lhandle_per:  .long  do_single_step
-.Ljump_table:  .long  pgm_check_table
-.Lschedule:    .long  schedule
-.Lclone:       .long  sys_clone
-.Lexecve:      .long  sys_execve
-.Lfork:        .long  sys_fork
-.Lrt_sigreturn:.long  sys_rt_sigreturn
+		.long	s390_handle_mcck
+.Lmck_old_psw:	.long	__LC_MCK_OLD_PSW
+.Ldo_IRQ:	.long	do_IRQ
+.Ldo_extint:	.long	do_extint
+.Ldo_signal:	.long	do_signal
+.Lhandle_per:	.long	do_single_step
+.Ljump_table:	.long	pgm_check_table
+.Lschedule:	.long	schedule
+.Lclone:	.long	sys_clone
+.Lexecve:	.long	sys_execve
+.Lfork: 	.long	sys_fork
+.Lrt_sigreturn: .long	sys_rt_sigreturn
 .Lrt_sigsuspend:
-               .long  sys_rt_sigsuspend
-.Lsigreturn:   .long  sys_sigreturn
-.Lsigsuspend:  .long  sys_sigsuspend
-.Lsigaltstack: .long  sys_sigaltstack
-.Ltrace:       .long  syscall_trace
-.Lvfork:       .long  sys_vfork
-.Lschedtail:   .long  schedule_tail
-.Lsysc_table:  .long  sys_call_table
+		.long	sys_rt_sigsuspend
+.Lsigreturn:	.long	sys_sigreturn
+.Lsigsuspend:	.long	sys_sigsuspend
+.Lsigaltstack:	.long	sys_sigaltstack
+.Ltrace:	.long	syscall_trace
+.Lvfork:	.long	sys_vfork
+.Lschedtail:	.long	schedule_tail
+.Lsysc_table:	.long	sys_call_table
 #ifdef CONFIG_TRACE_IRQFLAGS
-.Ltrace_irq_on:.long  trace_hardirqs_on
+.Ltrace_irq_on: .long	trace_hardirqs_on
 .Ltrace_irq_off:
-	       .long  trace_hardirqs_off
+		.long	trace_hardirqs_off
 #endif
 .Lcritical_start:
-               .long  __critical_start + 0x80000000
+		.long	__critical_start + 0x80000000
 .Lcritical_end:
-               .long  __critical_end + 0x80000000
+		.long	__critical_end + 0x80000000
 .Lcleanup_critical:
-               .long  cleanup_critical
+		.long	cleanup_critical
 
-	       .section .rodata, "a"
+		.section .rodata, "a"
 #define SYSCALL(esa,esame,emu)	.long esa
 sys_call_table:
 #include "syscalls.S"
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 29bbfba..0f758c3 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -4,8 +4,8 @@
  *
  *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *               Hartmut Penner (hp@de.ibm.com),
- *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *		 Hartmut Penner (hp@de.ibm.com),
+ *		 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
@@ -24,29 +24,29 @@
  * Stack layout for the system_call stack entry.
  * The first few entries are identical to the user_regs_struct.
  */
-SP_PTREGS    =  STACK_FRAME_OVERHEAD
-SP_ARGS      =  STACK_FRAME_OVERHEAD + __PT_ARGS
-SP_PSW       =  STACK_FRAME_OVERHEAD + __PT_PSW
-SP_R0        =  STACK_FRAME_OVERHEAD + __PT_GPRS
-SP_R1        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 8
-SP_R2        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 16
-SP_R3        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 24
-SP_R4        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 32
-SP_R5        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 40
-SP_R6        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 48
-SP_R7        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 56
-SP_R8        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 64
-SP_R9        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 72
-SP_R10       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 80
-SP_R11       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 88
-SP_R12       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 96
-SP_R13       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 104
-SP_R14       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 112
-SP_R15       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 120
-SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC       =  STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
-SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
+SP_PTREGS    =	STACK_FRAME_OVERHEAD
+SP_ARGS      =	STACK_FRAME_OVERHEAD + __PT_ARGS
+SP_PSW	     =	STACK_FRAME_OVERHEAD + __PT_PSW
+SP_R0	     =	STACK_FRAME_OVERHEAD + __PT_GPRS
+SP_R1	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 8
+SP_R2	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 16
+SP_R3	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 24
+SP_R4	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 32
+SP_R5	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 40
+SP_R6	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 48
+SP_R7	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 56
+SP_R8	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 64
+SP_R9	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 72
+SP_R10	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 80
+SP_R11	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 88
+SP_R12	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 96
+SP_R13	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 104
+SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 112
+SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 120
+SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
+SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
+SP_TRAP      =	STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -71,14 +71,14 @@
 #define TRACE_IRQS_OFF
 #endif
 
-	.macro  STORE_TIMER lc_offset
+	.macro	STORE_TIMER lc_offset
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	stpt	\lc_offset
 #endif
 	.endm
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	.macro  UPDATE_VTIME lc_from,lc_to,lc_sum
+	.macro	UPDATE_VTIME lc_from,lc_to,lc_sum
 	lg	%r10,\lc_from
 	slg	%r10,\lc_to
 	alg	%r10,\lc_sum
@@ -94,7 +94,7 @@
  *    R15 - kernel stack pointer
  */
 
-        .macro  SAVE_ALL_BASE savearea
+	.macro	SAVE_ALL_BASE savearea
 	stmg	%r12,%r15,\savearea
 	larl	%r13,system_call
 	.endm
@@ -139,8 +139,8 @@
 	.endm
 
 	.macro	CREATE_STACK_FRAME psworg,savearea
-	aghi    %r15,-SP_SIZE		# make room for registers & psw
-	mvc     SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
+	aghi	%r15,-SP_SIZE		# make room for registers & psw
+	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
 	stg	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
 	icm	%r12,12,__LC_SVC_ILC
@@ -149,7 +149,7 @@
 	mvc	SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
 	la	%r12,0
 	stg	%r12,__SF_BACKCHAIN(%r15)
-        .endm
+	.endm
 
 	.macro	RESTORE_ALL psworg,sync
 	mvc	\psworg(16),SP_PSW(%r15) # move user PSW to lowcore
@@ -168,29 +168,29 @@
  * Returns:
  *  gpr2 = prev
  */
-        .globl  __switch_to
+	.globl	__switch_to
 __switch_to:
 	tm	__THREAD_per+4(%r3),0xe8 # is the new process using per ?
 	jz	__switch_to_noper		# if not we're fine
-        stctg   %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
-        clc     __THREAD_per(24,%r3),__SF_EMPTY(%r15)
-        je      __switch_to_noper            # we got away without bashing TLB's
-        lctlg   %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
+	stctg	%c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
+	clc	__THREAD_per(24,%r3),__SF_EMPTY(%r15)
+	je	__switch_to_noper	     # we got away without bashing TLB's
+	lctlg	%c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
-	lg	%r4,__THREAD_info(%r2)              # get thread_info of prev
+	lg	%r4,__THREAD_info(%r2)		    # get thread_info of prev
 	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
 	jz	__switch_to_no_mcck
 	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
 	lg	%r4,__THREAD_info(%r3)		    # get thread_info of next
 	oi	__TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
 __switch_to_no_mcck:
-        stmg    %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
+	stmg	%r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	stg	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	lg	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
-        lmg     %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
+	lmg	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	stg	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
 	lctl	%c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
-	lg	%r3,__THREAD_info(%r3)  # load thread_info from task struct
+	lg	%r3,__THREAD_info(%r3)	# load thread_info from task struct
 	stg	%r3,__LC_THREAD_INFO
 	aghi	%r3,STACK_SIZE
 	stg	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
@@ -202,14 +202,14 @@
  * are executed with interrupts enabled.
  */
 
-	.globl  system_call
+	.globl	system_call
 system_call:
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
 	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-        CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-	llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+	llgh	%r7,__LC_SVC_INT_CODE	# get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 sysc_vtime:
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
@@ -222,45 +222,45 @@
 #endif
 sysc_do_svc:
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        slag    %r7,%r7,2         # *4 and test for svc 0
+	slag	%r7,%r7,2	# *4 and test for svc 0
 	jnz	sysc_nr_ok
 	# svc 0: system call number in %r1
 	cl	%r1,BASED(.Lnr_syscalls)
 	jnl	sysc_nr_ok
-	lgfr	%r7,%r1           # clear high word in r1
-	slag    %r7,%r7,2         # svc 0: system call number in %r1
+	lgfr	%r7,%r1 	# clear high word in r1
+	slag	%r7,%r7,2	# svc 0: system call number in %r1
 sysc_nr_ok:
 	mvc	SP_ARGS(8,%r15),SP_R7(%r15)
 sysc_do_restart:
-	larl    %r10,sys_call_table
+	larl	%r10,sys_call_table
 #ifdef CONFIG_COMPAT
 	tm	__TI_flags+5(%r9),(_TIF_31BIT>>16)  # running in 31 bit mode ?
 	jno	sysc_noemu
-	larl    %r10,sys_call_table_emu  # use 31 bit emulation system calls
+	larl	%r10,sys_call_table_emu  # use 31 bit emulation system calls
 sysc_noemu:
 #endif
 	tm	__TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
-        lgf     %r8,0(%r7,%r10)   # load address of system call routine
-        jnz     sysc_tracesys
-        basr    %r14,%r8          # call sys_xxxx
-        stg     %r2,SP_R2(%r15)   # store return value (change R2 on stack)
-                                  # ATTENTION: check sys_execve_glue before
-                                  # changing anything here !!
+	lgf	%r8,0(%r7,%r10) # load address of system call routine
+	jnz	sysc_tracesys
+	basr	%r14,%r8	# call sys_xxxx
+	stg	%r2,SP_R2(%r15) # store return value (change R2 on stack)
+				# ATTENTION: check sys_execve_glue before
+				# changing anything here !!
 
 sysc_return:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
-        jno     sysc_leave
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
+	jno	sysc_leave
 	tm	__TI_flags+7(%r9),_TIF_WORK_SVC
-	jnz	sysc_work         # there is work to do (signals etc.)
+	jnz	sysc_work	# there is work to do (signals etc.)
 sysc_leave:
-        RESTORE_ALL __LC_RETURN_PSW,1
+	RESTORE_ALL __LC_RETURN_PSW,1
 
 #
 # recheck if there is more work to do
 #
 sysc_work_loop:
 	tm	__TI_flags+7(%r9),_TIF_WORK_SVC
-	jz	sysc_leave        # there is no work to do
+	jz	sysc_leave	  # there is no work to do
 #
 # One of the work bits is on. Find out which one.
 #
@@ -279,25 +279,25 @@
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#	
-sysc_reschedule:        
-	larl    %r14,sysc_work_loop
-        jg      schedule            # return point is sysc_return
+#
+sysc_reschedule:
+	larl	%r14,sysc_work_loop
+	jg	schedule	# return point is sysc_return
 
 #
 # _TIF_MCCK_PENDING is set, call handler
 #
 sysc_mcck_pending:
 	larl	%r14,sysc_work_loop
-	jg	s390_handle_mcck    # TIF bit will be cleared by handler
+	jg	s390_handle_mcck	# TIF bit will be cleared by handler
 
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-sysc_sigpending:     
+sysc_sigpending:
 	ni	__TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-	brasl	%r14,do_signal    # call do_signal
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	brasl	%r14,do_signal		# call do_signal
 	tm	__TI_flags+7(%r9),_TIF_RESTART_SVC
 	jo	sysc_restart
 	tm	__TI_flags+7(%r9),_TIF_SINGLE_STEP
@@ -309,11 +309,11 @@
 #
 sysc_restart:
 	ni	__TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-	lg	%r7,SP_R2(%r15)        # load new svc number
-        slag    %r7,%r7,2              # *4
+	lg	%r7,SP_R2(%r15)		# load new svc number
+	slag	%r7,%r7,2		# *4
 	mvc	SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
-	lmg	%r2,%r6,SP_R2(%r15)    # load svc arguments
-	j	sysc_do_restart        # restart svc
+	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
+	j	sysc_do_restart 	# restart svc
 
 #
 # _TIF_SINGLE_STEP is set, call do_single_step
@@ -326,49 +326,48 @@
 	larl	%r14,sysc_return	# load adr. of system return
 	jg	do_single_step		# branch to do_sigtrap
 
-
 #
 # call syscall_trace before and after system call
 # special linkage: %r12 contains the return address for trace_svc
 #
 sysc_tracesys:
-	la	%r2,SP_PTREGS(%r15)    # load pt_regs
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,0
 	srl	%r7,2
-	stg     %r7,SP_R2(%r15)
-        brasl   %r14,syscall_trace
+	stg	%r7,SP_R2(%r15)
+	brasl	%r14,syscall_trace
 	lghi	%r0,NR_syscalls
 	clg	%r0,SP_R2(%r15)
 	jnh	sysc_tracenogo
-	lg	%r7,SP_R2(%r15)   # strace might have changed the
-	sll     %r7,2             #  system call
+	lg	%r7,SP_R2(%r15)		# strace might have changed the
+	sll	%r7,2			# system call
 	lgf	%r8,0(%r7,%r10)
 sysc_tracego:
-	lmg     %r3,%r6,SP_R3(%r15)
-	lg      %r2,SP_ORIG_R2(%r15)
-        basr    %r14,%r8            # call sys_xxx
-        stg     %r2,SP_R2(%r15)     # store return value
+	lmg	%r3,%r6,SP_R3(%r15)
+	lg	%r2,SP_ORIG_R2(%r15)
+	basr	%r14,%r8		# call sys_xxx
+	stg	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
 	tm	__TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
-        jz      sysc_return
-	la	%r2,SP_PTREGS(%r15)    # load pt_regs
+	jz	sysc_return
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	la	%r3,1
-	larl	%r14,sysc_return    # return point is sysc_return
+	larl	%r14,sysc_return	# return point is sysc_return
 	jg	syscall_trace
 
 #
 # a new process exits the kernel with ret_from_fork
 #
-        .globl  ret_from_fork
+	.globl	ret_from_fork
 ret_from_fork:
 	lg	%r13,__LC_SVC_NEW_PSW+8
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
 	jo	0f
 	stg	%r15,SP_R15(%r15)	# store stack pointer for new kthread
-0:	brasl   %r14,schedule_tail
+0:	brasl	%r14,schedule_tail
 	TRACE_IRQS_ON
-        stosm   24(%r15),0x03     # reenable interrupts
+	stosm	24(%r15),0x03		# reenable interrupts
 	j	sysc_return
 
 #
@@ -377,78 +376,78 @@
 # but are called with different parameter.
 # return-address is set up above
 #
-sys_clone_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys_clone              # branch to sys_clone
+sys_clone_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	jg	sys_clone		# branch to sys_clone
 
 #ifdef CONFIG_COMPAT
-sys32_clone_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys32_clone            # branch to sys32_clone
+sys32_clone_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	jg	sys32_clone		# branch to sys32_clone
 #endif
 
-sys_fork_glue:  
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys_fork               # branch to sys_fork
+sys_fork_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	jg	sys_fork		# branch to sys_fork
 
-sys_vfork_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys_vfork              # branch to sys_vfork
+sys_vfork_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	jg	sys_vfork		# branch to sys_vfork
 
-sys_execve_glue:        
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs
-	lgr     %r12,%r14             # save return address
-        brasl   %r14,sys_execve       # call sys_execve
-        ltgr    %r2,%r2               # check if execve failed
-        bnz     0(%r12)               # it did fail -> store result in gpr2
-        b       6(%r12)               # SKIP STG 2,SP_R2(15) in
-                                      # system_call/sysc_tracesys
+sys_execve_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	lgr	%r12,%r14		# save return address
+	brasl	%r14,sys_execve 	# call sys_execve
+	ltgr	%r2,%r2 		# check if execve failed
+	bnz	0(%r12) 		# it did fail -> store result in gpr2
+	b	6(%r12) 		# SKIP STG 2,SP_R2(15) in
+					# system_call/sysc_tracesys
 #ifdef CONFIG_COMPAT
-sys32_execve_glue:        
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs
-	lgr     %r12,%r14             # save return address
-        brasl   %r14,sys32_execve     # call sys32_execve
-        ltgr    %r2,%r2               # check if execve failed
-        bnz     0(%r12)               # it did fail -> store result in gpr2
-        b       6(%r12)               # SKIP STG 2,SP_R2(15) in
-                                      # system_call/sysc_tracesys
+sys32_execve_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	lgr	%r12,%r14		# save return address
+	brasl	%r14,sys32_execve	# call sys32_execve
+	ltgr	%r2,%r2 		# check if execve failed
+	bnz	0(%r12) 		# it did fail -> store result in gpr2
+	b	6(%r12) 		# SKIP STG 2,SP_R2(15) in
+					# system_call/sysc_tracesys
 #endif
 
-sys_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys_sigreturn         # branch to sys_sigreturn
+sys_sigreturn_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs as parameter
+	jg	sys_sigreturn		# branch to sys_sigreturn
 
 #ifdef CONFIG_COMPAT
-sys32_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys32_sigreturn       # branch to sys32_sigreturn
+sys32_sigreturn_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs as parameter
+	jg	sys32_sigreturn 	# branch to sys32_sigreturn
 #endif
 
-sys_rt_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys_rt_sigreturn      # branch to sys_sigreturn
+sys_rt_sigreturn_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs as parameter
+	jg	sys_rt_sigreturn	# branch to sys_sigreturn
 
 #ifdef CONFIG_COMPAT
-sys32_rt_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys32_rt_sigreturn    # branch to sys32_sigreturn
+sys32_rt_sigreturn_glue:
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs as parameter
+	jg	sys32_rt_sigreturn	# branch to sys32_sigreturn
 #endif
 
 sys_sigaltstack_glue:
-        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys_sigaltstack       # branch to sys_sigreturn
+	la	%r4,SP_PTREGS(%r15)	# load pt_regs as parameter
+	jg	sys_sigaltstack 	# branch to sys_sigreturn
 
 #ifdef CONFIG_COMPAT
 sys32_sigaltstack_glue:
-        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys32_sigaltstack_wrapper # branch to sys_sigreturn
+	la	%r4,SP_PTREGS(%r15)	# load pt_regs as parameter
+	jg	sys32_sigaltstack_wrapper # branch to sys_sigreturn
 #endif
 
 /*
  * Program check handler routine
  */
 
-        .globl  pgm_check_handler
+	.globl	pgm_check_handler
 pgm_check_handler:
 /*
  * First we need to check for a special case:
@@ -465,8 +464,8 @@
  */
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 	SAVE_ALL_BASE __LC_SAVE_AREA
-        tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
-        jnz     pgm_per                  # got per exception -> special case
+	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+	jnz	pgm_per 		 # got per exception -> special case
 	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -478,29 +477,29 @@
 pgm_no_vtime:
 #endif
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-	lgf     %r3,__LC_PGM_ILC	 # load program interruption code
+	lgf	%r3,__LC_PGM_ILC	# load program interruption code
 	lghi	%r8,0x7f
 	ngr	%r8,%r3
 pgm_do_call:
-        sll     %r8,3
-        larl    %r1,pgm_check_table
-        lg      %r1,0(%r8,%r1)		 # load address of handler routine
-        la      %r2,SP_PTREGS(%r15)	 # address of register-save area
+	sll	%r8,3
+	larl	%r1,pgm_check_table
+	lg	%r1,0(%r8,%r1)		# load address of handler routine
+	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	larl	%r14,sysc_return
-        br      %r1			 # branch to interrupt-handler
+	br	%r1			# branch to interrupt-handler
 
 #
 # handle per exception
 #
 pgm_per:
-        tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
-        jnz     pgm_per_std              # ok, normal per event from user space
+	tm	__LC_PGM_OLD_PSW,0x40	# test if per event recording is on
+	jnz	pgm_per_std		# ok, normal per event from user space
 # ok its one of the special cases, now we need to find out which one
-        clc     __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
-        je      pgm_svcper
+	clc	__LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
+	je	pgm_svcper
 # no interesting special case, ignore PER event
 	lmg	%r12,%r15,__LC_SAVE_AREA
-	lpswe   __LC_PGM_OLD_PSW
+	lpswe	__LC_PGM_OLD_PSW
 
 #
 # Normal per exception
@@ -524,9 +523,9 @@
 	mvc	__THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
 	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
 	oi	__TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-	lgf     %r3,__LC_PGM_ILC	 # load program interruption code
+	lgf	%r3,__LC_PGM_ILC	# load program interruption code
 	lghi	%r8,0x7f
-	ngr	%r8,%r3			 # clear per-event-bit and ilc
+	ngr	%r8,%r3			# clear per-event-bit and ilc
 	je	sysc_return
 	j	pgm_do_call
 
@@ -544,7 +543,7 @@
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime3:
 #endif
-	llgh    %r7,__LC_SVC_INT_CODE	# get svc number from lowcore
+	llgh	%r7,__LC_SVC_INT_CODE	# get svc number from lowcore
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	lg	%r1,__TI_task(%r9)
 	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
@@ -568,7 +567,7 @@
 /*
  * IO interrupt handler routine
  */
-        .globl io_int_handler
+	.globl io_int_handler
 io_int_handler:
 	STORE_TIMER __LC_ASYNC_ENTER_TIMER
 	stck	__LC_INT_CLOCK
@@ -585,42 +584,42 @@
 #endif
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	TRACE_IRQS_OFF
-        la      %r2,SP_PTREGS(%r15)    # address of register-save area
-	brasl   %r14,do_IRQ            # call standard irq handler
+	la	%r2,SP_PTREGS(%r15)	# address of register-save area
+	brasl	%r14,do_IRQ		# call standard irq handler
 	TRACE_IRQS_ON
 
 io_return:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
 #ifdef CONFIG_PREEMPT
-	jno     io_preempt             # no -> check for preemptive scheduling
+	jno	io_preempt		# no -> check for preemptive scheduling
 #else
-        jno     io_leave               # no-> skip resched & signal
+	jno	io_leave		# no-> skip resched & signal
 #endif
 	tm	__TI_flags+7(%r9),_TIF_WORK_INT
-	jnz	io_work                # there is work to do (signals etc.)
+	jnz	io_work 		# there is work to do (signals etc.)
 io_leave:
-        RESTORE_ALL __LC_RETURN_PSW,0
+	RESTORE_ALL __LC_RETURN_PSW,0
 io_done:
 
 #ifdef CONFIG_PREEMPT
 io_preempt:
-	icm	%r0,15,__TI_precount(%r9)	
-	jnz     io_leave
+	icm	%r0,15,__TI_precount(%r9)
+	jnz	io_leave
 	# switch to kernel stack
 	lg	%r1,SP_R15(%r15)
 	aghi	%r1,-SP_SIZE
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lgr	%r15,%r1
 io_resume_loop:
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jno	io_leave
-	larl    %r1,.Lc_pactive
-	mvc     __TI_precount(4,%r9),0(%r1)
-        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
-	brasl   %r14,schedule          # call schedule
-        stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
-	xc      __TI_precount(4,%r9),__TI_precount(%r9)
+	larl	%r1,.Lc_pactive
+	mvc	__TI_precount(4,%r9),0(%r1)
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
+	brasl	%r14,schedule		# call schedule
+	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
+	xc	__TI_precount(4,%r9),__TI_precount(%r9)
 	j	io_resume_loop
 #endif
 
@@ -631,7 +630,7 @@
 	lg	%r1,__LC_KERNEL_STACK
 	aghi	%r1,-SP_SIZE
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lgr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
@@ -656,11 +655,11 @@
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#	
-io_reschedule:        
-	stosm   __SF_EMPTY(%r15),0x03	# reenable interrupts
-	brasl   %r14,schedule		# call scheduler
-	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
+#
+io_reschedule:
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
+	brasl	%r14,schedule		# call scheduler
+	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
 	tm	__TI_flags+7(%r9),_TIF_WORK_INT
 	jz	io_leave		# there is no work to do
 	j	io_work_loop
@@ -668,17 +667,17 @@
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-io_sigpending:     
-	stosm   __SF_EMPTY(%r15),0x03	# reenable interrupts
-	la      %r2,SP_PTREGS(%r15)	# load pt_regs
+io_sigpending:
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	brasl	%r14,do_signal		# call do_signal
-	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
+	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
 	j	io_work_loop
 
 /*
  * External interrupt handler routine
  */
-        .globl  ext_int_handler
+	.globl	ext_int_handler
 ext_int_handler:
 	STORE_TIMER __LC_ASYNC_ENTER_TIMER
 	stck	__LC_INT_CLOCK
@@ -695,9 +694,9 @@
 #endif
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	TRACE_IRQS_OFF
-	la	%r2,SP_PTREGS(%r15)    # address of register-save area
-	llgh	%r3,__LC_EXT_INT_CODE  # get interruption code
-	brasl   %r14,do_extint
+	la	%r2,SP_PTREGS(%r15)	# address of register-save area
+	llgh	%r3,__LC_EXT_INT_CODE	# get interruption code
+	brasl	%r14,do_extint
 	TRACE_IRQS_ON
 	j	io_return
 
@@ -706,14 +705,14 @@
 /*
  * Machine check handler routines
  */
-        .globl mcck_int_handler
+	.globl mcck_int_handler
 mcck_int_handler:
 	la	%r1,4095		# revalidate r1
 	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
-  	lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
+	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
 	SAVE_ALL_BASE __LC_SAVE_AREA+64
 	la	%r12,__LC_MCK_OLD_PSW
-	tm	__LC_MCCK_CODE,0x80     # system damage?
+	tm	__LC_MCCK_CODE,0x80	# system damage?
 	jo	mcck_int_main		# yes -> rest of mcck code invalid
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	la	%r14,4095
@@ -737,19 +736,19 @@
 #endif
 	tm	__LC_MCCK_CODE+2,0x09	# mwp + ia of old psw valid?
 	jno	mcck_int_main		# no -> skip cleanup critical
-	tm      __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
+	tm	__LC_MCK_OLD_PSW+1,0x01 # test problem state bit
 	jnz	mcck_int_main		# from user -> load kernel stack
 	clc	__LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
 	jhe	mcck_int_main
-	clc     __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
+	clc	__LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
 	jl	mcck_int_main
-	brasl   %r14,cleanup_critical
+	brasl	%r14,cleanup_critical
 mcck_int_main:
-	lg      %r14,__LC_PANIC_STACK   # are we already on the panic stack?
+	lg	%r14,__LC_PANIC_STACK	# are we already on the panic stack?
 	slgr	%r14,%r15
 	srag	%r14,%r14,PAGE_SHIFT
 	jz	0f
-	lg      %r15,__LC_PANIC_STACK   # load panic stack
+	lg	%r15,__LC_PANIC_STACK	# load panic stack
 0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
@@ -764,7 +763,7 @@
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	brasl	%r14,s390_do_machine_check
-	tm	SP_PSW+1(%r15),0x01     # returning to user ?
+	tm	SP_PSW+1(%r15),0x01	# returning to user ?
 	jno	mcck_return
 	lg	%r1,__LC_KERNEL_STACK	# switch to kernel stack
 	aghi	%r1,-SP_SIZE
@@ -794,28 +793,28 @@
 /*
  * Restart interruption handler, kick starter for additional CPUs
  */
-        .globl restart_int_handler
+	.globl restart_int_handler
 restart_int_handler:
-        lg      %r15,__LC_SAVE_AREA+120 # load ksp
-        lghi    %r10,__LC_CREGS_SAVE_AREA
-        lctlg   %c0,%c15,0(%r10) # get new ctl regs
-        lghi    %r10,__LC_AREGS_SAVE_AREA
-        lam     %a0,%a15,0(%r10)
-        lmg     %r6,%r15,__SF_GPRS(%r15) # load registers from clone
-        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
-	jg      start_secondary
+	lg	%r15,__LC_SAVE_AREA+120 # load ksp
+	lghi	%r10,__LC_CREGS_SAVE_AREA
+	lctlg	%c0,%c15,0(%r10) # get new ctl regs
+	lghi	%r10,__LC_AREGS_SAVE_AREA
+	lam	%a0,%a15,0(%r10)
+	lmg	%r6,%r15,__SF_GPRS(%r15) # load registers from clone
+	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
+	jg	start_secondary
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-        .globl restart_int_handler
+	.globl restart_int_handler
 restart_int_handler:
-        basr    %r1,0
+	basr	%r1,0
 restart_base:
-        lpswe   restart_crash-restart_base(%r1)
-        .align 8
+	lpswe	restart_crash-restart_base(%r1)
+	.align 8
 restart_crash:
-        .long  0x000a0000,0x00000000,0x00000000,0x00000000
+	.long  0x000a0000,0x00000000,0x00000000,0x00000000
 restart_go:
 #endif
 
@@ -836,9 +835,9 @@
 	chi	%r12,__LC_PGM_OLD_PSW
 	je	0f
 	la	%r1,__LC_SAVE_AREA+32
-0:	mvc	SP_R12(32,%r15),0(%r1)  # move %r12-%r15 to stack
-        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
-        la      %r2,SP_PTREGS(%r15)	# load pt_regs
+0:	mvc	SP_R12(32,%r15),0(%r1)	# move %r12-%r15 to stack
+	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	jg	kernel_stack_overflow
 #endif
 
@@ -941,10 +940,10 @@
 cleanup_system_call_insn:
 	.quad	sysc_saveall
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	.quad   system_call
-	.quad   sysc_vtime
-	.quad   sysc_stime
-	.quad   sysc_update
+	.quad	system_call
+	.quad	sysc_vtime
+	.quad	sysc_stime
+	.quad	sysc_update
 #endif
 
 cleanup_sysc_return:
@@ -1010,21 +1009,21 @@
 /*
  * Integer constants
  */
-               .align 4
+		.align	4
 .Lconst:
-.Lc_pactive:   .long  PREEMPT_ACTIVE
-.Lnr_syscalls: .long  NR_syscalls
-.L0x0130:      .short 0x130
-.L0x0140:      .short 0x140
-.L0x0150:      .short 0x150
-.L0x0160:      .short 0x160
-.L0x0170:      .short 0x170
+.Lc_pactive:	.long	PREEMPT_ACTIVE
+.Lnr_syscalls:	.long	NR_syscalls
+.L0x0130:	.short	0x130
+.L0x0140:	.short	0x140
+.L0x0150:	.short	0x150
+.L0x0160:	.short	0x160
+.L0x0170:	.short	0x170
 .Lcritical_start:
-               .quad  __critical_start
+		.quad	__critical_start
 .Lcritical_end:
-               .quad  __critical_end
+		.quad	__critical_end
 
-	       .section .rodata, "a"
+		.section .rodata, "a"
 #define SYSCALL(esa,esame,emu)	.long esame
 sys_call_table:
 #include "syscalls.S"
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 0f1db26..0cf59bb 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -36,449 +36,449 @@
 #endif
 
 #ifndef CONFIG_IPL
-        .org   0
-        .long  0x00080000,0x80000000+startup   # Just a restart PSW
+	.org   0
+	.long  0x00080000,0x80000000+startup	# Just a restart PSW
 #else
 #ifdef CONFIG_IPL_TAPE
 #define IPL_BS 1024
-        .org   0
-        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
-        .long  0x27000000,0x60000001           # by ipl to addresses 0-23.
-        .long  0x02000000,0x20000000+IPL_BS    # (a PSW and two CCWs).
-        .long  0x00000000,0x00000000           # external old psw
-        .long  0x00000000,0x00000000           # svc old psw
-        .long  0x00000000,0x00000000           # program check old psw
-        .long  0x00000000,0x00000000           # machine check old psw
-        .long  0x00000000,0x00000000           # io old psw
-        .long  0x00000000,0x00000000
-        .long  0x00000000,0x00000000
-        .long  0x00000000,0x00000000
-        .long  0x000a0000,0x00000058           # external new psw
-        .long  0x000a0000,0x00000060           # svc new psw
-        .long  0x000a0000,0x00000068           # program check new psw
-        .long  0x000a0000,0x00000070           # machine check new psw
-        .long  0x00080000,0x80000000+.Lioint   # io new psw
+	.org   0
+	.long  0x00080000,0x80000000+iplstart	# The first 24 bytes are loaded
+	.long  0x27000000,0x60000001		# by ipl to addresses 0-23.
+	.long  0x02000000,0x20000000+IPL_BS	# (a PSW and two CCWs).
+	.long  0x00000000,0x00000000		# external old psw
+	.long  0x00000000,0x00000000		# svc old psw
+	.long  0x00000000,0x00000000		# program check old psw
+	.long  0x00000000,0x00000000		# machine check old psw
+	.long  0x00000000,0x00000000		# io old psw
+	.long  0x00000000,0x00000000
+	.long  0x00000000,0x00000000
+	.long  0x00000000,0x00000000
+	.long  0x000a0000,0x00000058		# external new psw
+	.long  0x000a0000,0x00000060		# svc new psw
+	.long  0x000a0000,0x00000068		# program check new psw
+	.long  0x000a0000,0x00000070		# machine check new psw
+	.long  0x00080000,0x80000000+.Lioint	# io new psw
 
-        .org   0x100
+	.org   0x100
 #
 # subroutine for loading from tape
-# Paramters:	
+# Paramters:
 #  R1 = device number
 #  R2 = load address
-.Lloader:	
-        st    %r14,.Lldret
-        la    %r3,.Lorbread                    # r3 = address of orb 
-	la    %r5,.Lirb                        # r5 = address of irb
-        st    %r2,.Lccwread+4                  # initialize CCW data addresses
-        lctl  %c6,%c6,.Lcr6               
-        slr   %r2,%r2
+.Lloader:
+	st	%r14,.Lldret
+	la	%r3,.Lorbread		# r3 = address of orb
+	la	%r5,.Lirb		# r5 = address of irb
+	st	%r2,.Lccwread+4 	# initialize CCW data addresses
+	lctl	%c6,%c6,.Lcr6
+	slr	%r2,%r2
 .Lldlp:
-        la    %r6,3                            # 3 retries
+	la	%r6,3			# 3 retries
 .Lssch:
-        ssch  0(%r3)                           # load chunk of IPL_BS bytes
-        bnz   .Llderr
+	ssch	0(%r3)			# load chunk of IPL_BS bytes
+	bnz	.Llderr
 .Lw4end:
-        bas   %r14,.Lwait4io
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Lrecov
-        slr   %r7,%r7
-        icm   %r7,3,10(%r5)                    # get residual count
-        lcr   %r7,%r7
-        la    %r7,IPL_BS(%r7)                  # IPL_BS-residual=#bytes read
-        ar    %r2,%r7                          # add to total size
-        tm    8(%r5),0x01                      # found a tape mark ?
-        bnz   .Ldone
-        l     %r0,.Lccwread+4                  # update CCW data addresses
-        ar    %r0,%r7
-        st    %r0,.Lccwread+4                
-        b     .Lldlp
+	bas	%r14,.Lwait4io
+	tm	8(%r5),0x82		# do we have a problem ?
+	bnz	.Lrecov
+	slr	%r7,%r7
+	icm	%r7,3,10(%r5)		# get residual count
+	lcr	%r7,%r7
+	la	%r7,IPL_BS(%r7) 	# IPL_BS-residual=#bytes read
+	ar	%r2,%r7 		# add to total size
+	tm	8(%r5),0x01		# found a tape mark ?
+	bnz	.Ldone
+	l	%r0,.Lccwread+4 	# update CCW data addresses
+	ar	%r0,%r7
+	st	%r0,.Lccwread+4
+	b	.Lldlp
 .Ldone:
-        l     %r14,.Lldret
-        br    %r14                             # r2 contains the total size
+	l	%r14,.Lldret
+	br	%r14			# r2 contains the total size
 .Lrecov:
-        bas   %r14,.Lsense                     # do the sensing
-        bct   %r6,.Lssch                       # dec. retry count & branch
-        b     .Llderr
+	bas	%r14,.Lsense		# do the sensing
+	bct	%r6,.Lssch		# dec. retry count & branch
+	b	.Llderr
 #
 # Sense subroutine
 #
 .Lsense:
-        st    %r14,.Lsnsret
-        la    %r7,.Lorbsense              
-        ssch  0(%r7)                           # start sense command
-        bnz   .Llderr
-        bas   %r14,.Lwait4io
-        l     %r14,.Lsnsret
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Llderr
-        br    %r14
+	st	%r14,.Lsnsret
+	la	%r7,.Lorbsense
+	ssch	0(%r7)			# start sense command
+	bnz	.Llderr
+	bas	%r14,.Lwait4io
+	l	%r14,.Lsnsret
+	tm	8(%r5),0x82		# do we have a problem ?
+	bnz	.Llderr
+	br	%r14
 #
 # Wait for interrupt subroutine
 #
 .Lwait4io:
-        lpsw  .Lwaitpsw                 
+	lpsw	.Lwaitpsw
 .Lioint:
-        c     %r1,0xb8                         # compare subchannel number
-        bne   .Lwait4io
-        tsch  0(%r5)
-        slr   %r0,%r0
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Lwtexit
-        tm    8(%r5),0x04                      # got device end ?
-        bz    .Lwait4io
+	c	%r1,0xb8		# compare subchannel number
+	bne	.Lwait4io
+	tsch	0(%r5)
+	slr	%r0,%r0
+	tm	8(%r5),0x82		# do we have a problem ?
+	bnz	.Lwtexit
+	tm	8(%r5),0x04		# got device end ?
+	bz	.Lwait4io
 .Lwtexit:
-        br    %r14
+	br	%r14
 .Llderr:
-        lpsw  .Lcrash              
+	lpsw	.Lcrash
 
-        .align 8
+	.align	8
 .Lorbread:
-	.long  0x00000000,0x0080ff00,.Lccwread
-        .align 8
+	.long	0x00000000,0x0080ff00,.Lccwread
+	.align	8
 .Lorbsense:
-        .long  0x00000000,0x0080ff00,.Lccwsense
-        .align 8
+	.long	0x00000000,0x0080ff00,.Lccwsense
+	.align	8
 .Lccwread:
-        .long  0x02200000+IPL_BS,0x00000000
+	.long	0x02200000+IPL_BS,0x00000000
 .Lccwsense:
-        .long  0x04200001,0x00000000
+	.long	0x04200001,0x00000000
 .Lwaitpsw:
-	.long  0x020a0000,0x80000000+.Lioint
+	.long	0x020a0000,0x80000000+.Lioint
 
-.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6:  .long  0xff000000
-        .align 8
-.Lcrash:.long  0x000a0000,0x00000000
-.Lldret:.long  0
+.Lirb:	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6:	.long	0xff000000
+	.align	8
+.Lcrash:.long	0x000a0000,0x00000000
+.Lldret:.long	0
 .Lsnsret: .long 0
-#endif  /* CONFIG_IPL_TAPE */
+#endif	/* CONFIG_IPL_TAPE */
 
 #ifdef CONFIG_IPL_VM
-#define IPL_BS 0x730
-        .org   0
-        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
-        .long  0x02000018,0x60000050           # by ipl to addresses 0-23.
-        .long  0x02000068,0x60000050           # (a PSW and two CCWs).
-        .fill  80-24,1,0x40                    # bytes 24-79 are discarded !!
-        .long  0x020000f0,0x60000050           # The next 160 byte are loaded
-        .long  0x02000140,0x60000050           # to addresses 0x18-0xb7
-        .long  0x02000190,0x60000050           # They form the continuation
-        .long  0x020001e0,0x60000050           # of the CCW program started
-        .long  0x02000230,0x60000050           # by ipl and load the range
-        .long  0x02000280,0x60000050           # 0x0f0-0x730 from the image
-        .long  0x020002d0,0x60000050           # to the range 0x0f0-0x730
-        .long  0x02000320,0x60000050           # in memory. At the end of
-        .long  0x02000370,0x60000050           # the channel program the PSW
-        .long  0x020003c0,0x60000050           # at location 0 is loaded.
-        .long  0x02000410,0x60000050           # Initial processing starts
-        .long  0x02000460,0x60000050           # at 0xf0 = iplstart.
-        .long  0x020004b0,0x60000050
-        .long  0x02000500,0x60000050
-        .long  0x02000550,0x60000050
-        .long  0x020005a0,0x60000050
-        .long  0x020005f0,0x60000050
-        .long  0x02000640,0x60000050
-        .long  0x02000690,0x60000050
-        .long  0x020006e0,0x20000050
+#define IPL_BS	0x730
+	.org	0
+	.long	0x00080000,0x80000000+iplstart	# The first 24 bytes are loaded
+	.long	0x02000018,0x60000050		# by ipl to addresses 0-23.
+	.long	0x02000068,0x60000050		# (a PSW and two CCWs).
+	.fill	80-24,1,0x40			# bytes 24-79 are discarded !!
+	.long	0x020000f0,0x60000050		# The next 160 byte are loaded
+	.long	0x02000140,0x60000050		# to addresses 0x18-0xb7
+	.long	0x02000190,0x60000050		# They form the continuation
+	.long	0x020001e0,0x60000050		# of the CCW program started
+	.long	0x02000230,0x60000050		# by ipl and load the range
+	.long	0x02000280,0x60000050		# 0x0f0-0x730 from the image
+	.long	0x020002d0,0x60000050		# to the range 0x0f0-0x730
+	.long	0x02000320,0x60000050		# in memory. At the end of
+	.long	0x02000370,0x60000050		# the channel program the PSW
+	.long	0x020003c0,0x60000050		# at location 0 is loaded.
+	.long	0x02000410,0x60000050		# Initial processing starts
+	.long	0x02000460,0x60000050		# at 0xf0 = iplstart.
+	.long	0x020004b0,0x60000050
+	.long	0x02000500,0x60000050
+	.long	0x02000550,0x60000050
+	.long	0x020005a0,0x60000050
+	.long	0x020005f0,0x60000050
+	.long	0x02000640,0x60000050
+	.long	0x02000690,0x60000050
+	.long	0x020006e0,0x20000050
 
-        .org   0xf0
+	.org	0xf0
 #
 # subroutine for loading cards from the reader
 #
-.Lloader:	
-	la    %r3,.Lorb                        # r2 = address of orb into r2
-	la    %r5,.Lirb                        # r4 = address of irb
-        la    %r6,.Lccws              
-        la    %r7,20
+.Lloader:
+	la	%r3,.Lorb		# r2 = address of orb into r2
+	la	%r5,.Lirb		# r4 = address of irb
+	la	%r6,.Lccws
+	la	%r7,20
 .Linit:
-        st    %r2,4(%r6)                       # initialize CCW data addresses
-        la    %r2,0x50(%r2)
-        la    %r6,8(%r6)
-        bct   7,.Linit
+	st	%r2,4(%r6)		# initialize CCW data addresses
+	la	%r2,0x50(%r2)
+	la	%r6,8(%r6)
+	bct	7,.Linit
 
-        lctl  %c6,%c6,.Lcr6                    # set IO subclass mask
-	slr   %r2,%r2
+	lctl	%c6,%c6,.Lcr6		# set IO subclass mask
+	slr	%r2,%r2
 .Lldlp:
-        ssch  0(%r3)                           # load chunk of 1600 bytes
-        bnz   .Llderr
+	ssch	0(%r3)			# load chunk of 1600 bytes
+	bnz	.Llderr
 .Lwait4irq:
-        mvc   0x78(8),.Lnewpsw                 # set up IO interrupt psw
-        lpsw  .Lwaitpsw              
+	mvc	0x78(8),.Lnewpsw	# set up IO interrupt psw
+	lpsw	.Lwaitpsw
 .Lioint:
-        c     %r1,0xb8                         # compare subchannel number
-	bne   .Lwait4irq
-	tsch  0(%r5)
+	c	%r1,0xb8		# compare subchannel number
+	bne	.Lwait4irq
+	tsch	0(%r5)
 
-	slr   %r0,%r0
-	ic    %r0,8(%r5)                       # get device status
-	chi   %r0,8                            # channel end ?
-	be    .Lcont
-	chi   %r0,12                           # channel end + device end ?
-	be    .Lcont
+	slr	%r0,%r0
+	ic	%r0,8(%r5)		# get device status
+	chi	%r0,8			# channel end ?
+	be	.Lcont
+	chi	%r0,12			# channel end + device end ?
+	be	.Lcont
 
-        l     %r0,4(%r5)
-        s     %r0,8(%r3)                       # r0/8 = number of ccws executed
-        mhi   %r0,10                           # *10 = number of bytes in ccws
-        lh    %r3,10(%r5)                      # get residual count
-        sr    %r0,%r3                          # #ccws*80-residual=#bytes read
-	ar    %r2,%r0
-	
-        br    %r14                             # r2 contains the total size
+	l	%r0,4(%r5)
+	s	%r0,8(%r3)		# r0/8 = number of ccws executed
+	mhi	%r0,10			# *10 = number of bytes in ccws
+	lh	%r3,10(%r5)		# get residual count
+	sr	%r0,%r3 		# #ccws*80-residual=#bytes read
+	ar	%r2,%r0
+
+	br	%r14			# r2 contains the total size
 
 .Lcont:
-	ahi   %r2,0x640                        # add 0x640 to total size
-        la    %r6,.Lccws             
-        la    %r7,20
+	ahi	%r2,0x640		# add 0x640 to total size
+	la	%r6,.Lccws
+	la	%r7,20
 .Lincr:
-        l     %r0,4(%r6)                       # update CCW data addresses
-        ahi   %r0,0x640
-        st    %r0,4(%r6)
-        ahi   %r6,8
-        bct   7,.Lincr
+	l	%r0,4(%r6)		# update CCW data addresses
+	ahi	%r0,0x640
+	st	%r0,4(%r6)
+	ahi	%r6,8
+	bct	7,.Lincr
 
-        b     .Lldlp
+	b	.Lldlp
 .Llderr:
-        lpsw  .Lcrash              
+	lpsw	.Lcrash
 
-        .align 8
-.Lorb:	.long  0x00000000,0x0080ff00,.Lccws
-.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6:  .long  0xff000000
-.Lloadp:.long  0,0
-        .align 8
-.Lcrash:.long  0x000a0000,0x00000000
+	.align	8
+.Lorb:	.long	0x00000000,0x0080ff00,.Lccws
+.Lirb:	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6:	.long	0xff000000
+.Lloadp:.long	0,0
+	.align	8
+.Lcrash:.long	0x000a0000,0x00000000
 .Lnewpsw:
-        .long  0x00080000,0x80000000+.Lioint
+	.long	0x00080000,0x80000000+.Lioint
 .Lwaitpsw:
-        .long  0x020a0000,0x80000000+.Lioint
+	.long	0x020a0000,0x80000000+.Lioint
 
-        .align 8
-.Lccws: .rept  19
-        .long  0x02600050,0x00000000
-        .endr
-        .long  0x02200050,0x00000000
-#endif  /* CONFIG_IPL_VM */
+	.align	8
+.Lccws: .rept	19
+	.long	0x02600050,0x00000000
+	.endr
+	.long	0x02200050,0x00000000
+#endif	/* CONFIG_IPL_VM */
 
 iplstart:
-        lh    %r1,0xb8                         # test if subchannel number
-        bct   %r1,.Lnoload                     #  is valid
-	l     %r1,0xb8                         # load ipl subchannel number
-        la    %r2,IPL_BS                       # load start address
-        bas   %r14,.Lloader                    # load rest of ipl image
-        l     %r12,.Lparm                      # pointer to parameter area
-        st    %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
+	lh	%r1,0xb8		# test if subchannel number
+	bct	%r1,.Lnoload		#  is valid
+	l	%r1,0xb8		# load ipl subchannel number
+	la	%r2,IPL_BS		# load start address
+	bas	%r14,.Lloader		# load rest of ipl image
+	l	%r12,.Lparm		# pointer to parameter area
+	st	%r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
 
 #
 # load parameter file from ipl device
 #
 .Lagain1:
-	l     %r2,.Linitrd		       # ramdisk loc. is temp
-        bas   %r14,.Lloader                    # load parameter file
-        ltr   %r2,%r2                          # got anything ?
-        bz    .Lnopf
-	chi   %r2,895
-	bnh   .Lnotrunc
-	la    %r2,895
+	l	%r2,.Linitrd		# ramdisk loc. is temp
+	bas	%r14,.Lloader		# load parameter file
+	ltr	%r2,%r2 		# got anything ?
+	bz	.Lnopf
+	chi	%r2,895
+	bnh	.Lnotrunc
+	la	%r2,895
 .Lnotrunc:
-	l     %r4,.Linitrd
-	clc   0(3,%r4),.L_hdr		       # if it is HDRx
-	bz    .Lagain1			       # skip dataset header
-	clc   0(3,%r4),.L_eof		       # if it is EOFx
-	bz    .Lagain1			       # skip dateset trailer
-        la    %r5,0(%r4,%r2)
-        lr    %r3,%r2
+	l	%r4,.Linitrd
+	clc	0(3,%r4),.L_hdr		# if it is HDRx
+	bz	.Lagain1		# skip dataset header
+	clc	0(3,%r4),.L_eof		# if it is EOFx
+	bz	.Lagain1		# skip dateset trailer
+	la	%r5,0(%r4,%r2)
+	lr	%r3,%r2
 .Lidebc:
-        tm    0(%r5),0x80                      # high order bit set ?
-        bo    .Ldocv                           #  yes -> convert from EBCDIC
-        ahi   %r5,-1
-        bct   %r3,.Lidebc
-        b     .Lnocv
+	tm	0(%r5),0x80		# high order bit set ?
+	bo	.Ldocv			#  yes -> convert from EBCDIC
+	ahi	%r5,-1
+	bct	%r3,.Lidebc
+	b	.Lnocv
 .Ldocv:
-        l     %r3,.Lcvtab
-        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
-        tr    256(256,%r4),0(%r3)
-        tr    512(256,%r4),0(%r3)
-        tr    768(122,%r4),0(%r3)
-.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
-	mvc   0(256,%r3),0(%r4)
-	mvc   256(256,%r3),256(%r4)
-	mvc   512(256,%r3),512(%r4)
-	mvc   768(122,%r3),768(%r4)
-        slr   %r0,%r0
-        b     .Lcntlp
+	l	%r3,.Lcvtab
+	tr	0(256,%r4),0(%r3)	# convert parameters to ascii
+	tr	256(256,%r4),0(%r3)
+	tr	512(256,%r4),0(%r3)
+	tr	768(122,%r4),0(%r3)
+.Lnocv: la	%r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
+	mvc	0(256,%r3),0(%r4)
+	mvc	256(256,%r3),256(%r4)
+	mvc	512(256,%r3),512(%r4)
+	mvc	768(122,%r3),768(%r4)
+	slr	%r0,%r0
+	b	.Lcntlp
 .Ldelspc:
-        ic    %r0,0(%r2,%r3)
-        chi   %r0,0x20                         # is it a space ?
-        be    .Lcntlp
-        ahi   %r2,1
-        b     .Leolp
+	ic	%r0,0(%r2,%r3)
+	chi	%r0,0x20		# is it a space ?
+	be	.Lcntlp
+	ahi	%r2,1
+	b	.Leolp
 .Lcntlp:
-        brct  %r2,.Ldelspc
+	brct	%r2,.Ldelspc
 .Leolp:
-        slr   %r0,%r0
-        stc   %r0,0(%r2,%r3)                   # terminate buffer
+	slr	%r0,%r0
+	stc	%r0,0(%r2,%r3)		# terminate buffer
 .Lnopf:
 
 #
 # load ramdisk from ipl device
-#	
+#
 .Lagain2:
-	l     %r2,.Linitrd		       # addr of ramdisk
-	st    %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
-        bas   %r14,.Lloader                    # load ramdisk
- 	st    %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk
-        ltr   %r2,%r2
-        bnz   .Lrdcont
-        st    %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
+	l	%r2,.Linitrd		# addr of ramdisk
+	st	%r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
+	bas	%r14,.Lloader		# load ramdisk
+	st	%r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of rd
+	ltr	%r2,%r2
+	bnz	.Lrdcont
+	st	%r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
 .Lrdcont:
-	l     %r2,.Linitrd
+	l	%r2,.Linitrd
 
-	clc   0(3,%r2),.L_hdr		       # skip HDRx and EOFx 
-	bz    .Lagain2
-	clc   0(3,%r2),.L_eof
-	bz    .Lagain2
+	clc	0(3,%r2),.L_hdr		# skip HDRx and EOFx
+	bz	.Lagain2
+	clc	0(3,%r2),.L_eof
+	bz	.Lagain2
 
 #ifdef CONFIG_IPL_VM
 #
 # reset files in VM reader
 #
-        stidp __LC_CPUID                       # store cpuid
-	tm    __LC_CPUID,0xff                  # running VM ?
-	bno   .Lnoreset
-        la    %r2,.Lreset              
-        lhi   %r3,26
-	diag  %r2,%r3,8
-	la    %r5,.Lirb
-	stsch 0(%r5)			       # check if irq is pending
-	tm    30(%r5),0x0f		       # by verifying if any of the
-	bnz   .Lwaitforirq		       # activity or status control
-	tm    31(%r5),0xff		       # bits is set in the schib
-	bz    .Lnoreset
+	stidp	__LC_CPUID		# store cpuid
+	tm	__LC_CPUID,0xff 	# running VM ?
+	bno	.Lnoreset
+	la	%r2,.Lreset
+	lhi	%r3,26
+	diag	%r2,%r3,8
+	la	%r5,.Lirb
+	stsch	0(%r5)			# check if irq is pending
+	tm	30(%r5),0x0f		# by verifying if any of the
+	bnz	.Lwaitforirq		# activity or status control
+	tm	31(%r5),0xff		# bits is set in the schib
+	bz	.Lnoreset
 .Lwaitforirq:
-	mvc   0x78(8),.Lrdrnewpsw              # set up IO interrupt psw
+	mvc	0x78(8),.Lrdrnewpsw	# set up IO interrupt psw
 .Lwaitrdrirq:
-	lpsw  .Lrdrwaitpsw
+	lpsw	.Lrdrwaitpsw
 .Lrdrint:
-	c     %r1,0xb8                         # compare subchannel number
-	bne   .Lwaitrdrirq
-	la    %r5,.Lirb
-	tsch  0(%r5)
+	c	%r1,0xb8		# compare subchannel number
+	bne	.Lwaitrdrirq
+	la	%r5,.Lirb
+	tsch	0(%r5)
 .Lnoreset:
-        b     .Lnoload
+	b	.Lnoload
 
-	.align 8
+	.align	8
 .Lrdrnewpsw:
-	.long  0x00080000,0x80000000+.Lrdrint
+	.long	0x00080000,0x80000000+.Lrdrint
 .Lrdrwaitpsw:
-	.long  0x020a0000,0x80000000+.Lrdrint
+	.long	0x020a0000,0x80000000+.Lrdrint
 #endif
 
 #
 # everything loaded, go for it
 #
 .Lnoload:
-        l     %r1,.Lstartup
-        br    %r1
+	l	%r1,.Lstartup
+	br	%r1
 
-.Linitrd:.long _end + 0x400000		       # default address of initrd
+.Linitrd:.long _end + 0x400000		# default address of initrd
 .Lparm:	.long  PARMAREA
 .Lstartup: .long startup
-.Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
-.Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
-        .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
-        .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
-.L_eof: .long  0xc5d6c600       /* C'EOF' */
-.L_hdr: .long  0xc8c4d900       /* C'HDR' */
+.Lcvtab:.long	_ebcasc 		# ebcdic to ascii table
+.Lreset:.byte	0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
+	.byte	0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
+	.byte	0xc8,0xd6,0xd3,0xc4	# "change rdr all keep nohold"
+.L_eof: .long	0xc5d6c600	 /* C'EOF' */
+.L_hdr: .long	0xc8c4d900	 /* C'HDR' */
 
-#endif  /* CONFIG_IPL */
+#endif	/* CONFIG_IPL */
 
 #
 # SALIPL loader support. Based on a patch by Rob van der Heij.
 # This entry point is called directly from the SALIPL loader and
 # doesn't need a builtin ipl record.
 #
-        .org  0x800
-	.globl start
+	.org	0x800
+	.globl	start
 start:
-	stm   %r0,%r15,0x07b0		# store registers
-	basr  %r12,%r0
+	stm	%r0,%r15,0x07b0		# store registers
+	basr	%r12,%r0
 .base:
-	l     %r11,.parm
-	l     %r8,.cmd			# pointer to command buffer
+	l	%r11,.parm
+	l	%r8,.cmd		# pointer to command buffer
 
-	ltr   %r9,%r9			# do we have SALIPL parameters?
-	bp    .sk8x8
+	ltr	%r9,%r9			# do we have SALIPL parameters?
+	bp	.sk8x8
 
-	mvc   0(64,%r8),0x00b0		# copy saved registers
-	xc    64(240-64,%r8),0(%r8)	# remainder of buffer
-	tr    0(64,%r8),.lowcase	
-	b     .gotr
+	mvc	0(64,%r8),0x00b0	# copy saved registers
+	xc	64(240-64,%r8),0(%r8)	# remainder of buffer
+	tr	0(64,%r8),.lowcase
+	b	.gotr
 .sk8x8:
-	mvc   0(240,%r8),0(%r9)		# copy iplparms into buffer
+	mvc	0(240,%r8),0(%r9)	# copy iplparms into buffer
 .gotr:
-	l     %r10,.tbl			# EBCDIC to ASCII table
-	tr    0(240,%r8),0(%r10)
-	stidp __LC_CPUID		# Are we running on VM maybe
-	cli   __LC_CPUID,0xff
-	bnz   .test
-	.long 0x83300060		# diag 3,0,x'0060' - storage size
-	b     .done
+	l	%r10,.tbl		# EBCDIC to ASCII table
+	tr	0(240,%r8),0(%r10)
+	stidp	__LC_CPUID		# Are we running on VM maybe
+	cli	__LC_CPUID,0xff
+	bnz	.test
+	.long	0x83300060		# diag 3,0,x'0060' - storage size
+	b	.done
 .test:
-	mvc   0x68(8),.pgmnw		# set up pgm check handler
-	l     %r2,.fourmeg
-	lr    %r3,%r2
-	bctr  %r3,%r0			# 4M-1
-.loop:  iske  %r0,%r3
-	ar    %r3,%r2
+	mvc	0x68(8),.pgmnw		# set up pgm check handler
+	l	%r2,.fourmeg
+	lr	%r3,%r2
+	bctr	%r3,%r0			# 4M-1
+.loop:	iske	%r0,%r3
+	ar	%r3,%r2
 .pgmx:
-	sr    %r3,%r2
-	la    %r3,1(%r3)
+	sr	%r3,%r2
+	la	%r3,1(%r3)
 .done:
-        l     %r1,.memsize
-	st    %r3,ARCH_OFFSET(%r1)
-	slr   %r0,%r0
-	st    %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
-	st    %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
-	j     startup                   # continue with startup
-.tbl:	.long _ebcasc			# translate table
-.cmd:	.long COMMAND_LINE		# address of command line buffer
-.parm:	.long PARMAREA
+	l	%r1,.memsize
+	st	%r3,ARCH_OFFSET(%r1)
+	slr	%r0,%r0
+	st	%r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
+	st	%r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
+	j	startup 		# continue with startup
+.tbl:	.long	_ebcasc			# translate table
+.cmd:	.long	COMMAND_LINE		# address of command line buffer
+.parm:	.long	PARMAREA
 .memsize: .long memory_size
 .fourmeg: .long 0x00400000      	# 4M
-.pgmnw:	.long 0x00080000,.pgmx
+.pgmnw:	.long	0x00080000,.pgmx
 .lowcase:
-	.byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 
+	.byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
 	.byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
-	.byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 
+	.byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
 	.byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
-	.byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 
+	.byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
 	.byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
-	.byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 
+	.byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
 	.byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
-	.byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 
+	.byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
 	.byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
-	.byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 
+	.byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57
 	.byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
-	.byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 
+	.byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67
 	.byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
-	.byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 
+	.byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77
 	.byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
 
-	.byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 
+	.byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87
 	.byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
-	.byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 
+	.byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97
 	.byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
-	.byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 
+	.byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7
 	.byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
-	.byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 
+	.byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7
 	.byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
-	.byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87	# .abcdefg 
+	.byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87	# .abcdefg
 	.byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf	# hi
-	.byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 	# .jklmnop
+	.byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97	# .jklmnop
 	.byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf	# qr
 	.byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7	# ..stuvwx
 	.byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef	# yz
-	.byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 
+	.byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
 	.byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
 
 #ifdef CONFIG_64BIT
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index a8bdd96..48998d5 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -15,232 +15,232 @@
 # this is called either by the ipl loader or directly by PSW restart
 # or linload or SALIPL
 #
-	.org  0x10000
-startup:basr  %r13,0			 # get base
-.LPG0:	l     %r13,0f-.LPG0(%r13)
-	b     0(%r13)
-0:	.long startup_continue
+	.org	0x10000
+startup:basr	%r13,0			# get base
+.LPG0:	l	%r13,0f-.LPG0(%r13)
+	b	0(%r13)
+0:	.long	startup_continue
 
 #
 # params at 10400 (setup.h)
 #
-	.org   PARMAREA
-	.quad  0			# IPL_DEVICE
-	.quad  0			# INITRD_START
-	.quad  0			# INITRD_SIZE
+	.org	PARMAREA
+	.quad	0			# IPL_DEVICE
+	.quad	0			# INITRD_START
+	.quad	0			# INITRD_SIZE
 
-	.org   COMMAND_LINE
-	.byte  "root=/dev/ram0 ro"
-	.byte  0
+	.org	COMMAND_LINE
+	.byte	"root=/dev/ram0 ro"
+	.byte	0
 
-	.org   0x11000
+	.org	0x11000
 
 startup_continue:
-	basr  %r13,0			 # get base
-.LPG1:  sll   %r13,1                     # remove high order bit
-        srl   %r13,1
-        lhi   %r1,1                      # mode 1 = esame
-	mvi   __LC_AR_MODE_ID,1		 # set esame flag
-        slr   %r0,%r0                    # set cpuid to zero
-        sigp  %r1,%r0,0x12               # switch to esame mode
-	sam64				 # switch to 64 bit mode
-	lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
-	lg    %r12,.Lparmaddr-.LPG1(%r13)# pointer to parameter area
-					 # move IPL device to lowcore
-        mvc   __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
+	basr	%r13,0			# get base
+.LPG1:	sll	%r13,1			# remove high order bit
+	srl	%r13,1
+	lhi	%r1,1			# mode 1 = esame
+	mvi	__LC_AR_MODE_ID,1	# set esame flag
+	slr	%r0,%r0 		# set cpuid to zero
+	sigp	%r1,%r0,0x12		# switch to esame mode
+	sam64				# switch to 64 bit mode
+	lctlg	%c0,%c15,.Lctl-.LPG1(%r13)	# load control registers
+	lg	%r12,.Lparmaddr-.LPG1(%r13)	# pointer to parameter area
+					# move IPL device to lowcore
+	mvc	__LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
 #
 # Setup stack
 #
-	larl  %r15,init_thread_union
-	lg    %r14,__TI_task(%r15)	# cache current in lowcore
-	stg   %r14,__LC_CURRENT
-	aghi  %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
-	stg   %r15,__LC_KERNEL_STACK	# set end of kernel stack
-	aghi  %r15,-160
-	xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
+	larl	%r15,init_thread_union
+	lg	%r14,__TI_task(%r15)	# cache current in lowcore
+	stg	%r14,__LC_CURRENT
+	aghi	%r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
+	stg	%r15,__LC_KERNEL_STACK	# set end of kernel stack
+	aghi	%r15,-160
+	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
 
-	brasl %r14,ipl_save_parameters
+	brasl	%r14,ipl_save_parameters
 #
 # clear bss memory
 #
-	larl  %r2,__bss_start           # start of bss segment
-        larl  %r3,_end                  # end of bss segment
-        sgr   %r3,%r2                   # length of bss
-        sgr   %r4,%r4                   #
-        sgr   %r5,%r5                   # set src,length and pad to zero
-        mvcle %r2,%r4,0                 # clear mem
-        jo    .-4                       # branch back, if not finish
+	larl	%r2,__bss_start 	# start of bss segment
+	larl	%r3,_end		# end of bss segment
+	sgr	%r3,%r2 		# length of bss
+	sgr	%r4,%r4 		#
+	sgr	%r5,%r5 		# set src,length and pad to zero
+	mvcle	%r2,%r4,0		# clear mem
+	jo	.-4			# branch back, if not finish
 
-	l     %r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
+	l	%r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
 .Lservicecall:
-	stosm .Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts
+	stosm	.Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts
 
-	stctg %r0,%r0,.Lcr-.LPG1(%r13)	# get cr0
-	la    %r1,0x200			# set bit 22
-	og    %r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
-	stg   %r1,.Lcr-.LPG1(%r13)
-	lctlg %r0,%r0,.Lcr-.LPG1(%r13)	# load modified cr0
+	stctg	%r0,%r0,.Lcr-.LPG1(%r13)	# get cr0
+	la	%r1,0x200		# set bit 22
+	og	%r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
+	stg	%r1,.Lcr-.LPG1(%r13)
+	lctlg	%r0,%r0,.Lcr-.LPG1(%r13)	# load modified cr0
 
-	mvc   __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
-	larl  %r1,.Lsclph
-	stg   %r1,__LC_EXT_NEW_PSW+8	# set handler
+	mvc	__LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
+	larl	%r1,.Lsclph
+	stg	%r1,__LC_EXT_NEW_PSW+8	# set handler
 
-	larl  %r4,.Lsccb		# %r4 is our index for sccb stuff
-	lgr   %r1,%r4			# our sccb
-	.insn rre,0xb2200000,%r2,%r1	# service call
-	ipm   %r1
-	srl   %r1,28			# get cc code
-	xr    %r3,%r3
-	chi   %r1,3
-	be    .Lfchunk-.LPG1(%r13)	# leave
-	chi   %r1,2
-	be    .Lservicecall-.LPG1(%r13)
-	lpswe .Lwaitsclp-.LPG1(%r13)
+	larl	%r4,.Lsccb		# %r4 is our index for sccb stuff
+	lgr	%r1,%r4			# our sccb
+	.insn	rre,0xb2200000,%r2,%r1	# service call
+	ipm	%r1
+	srl	%r1,28			# get cc code
+	xr	%r3,%r3
+	chi	%r1,3
+	be	.Lfchunk-.LPG1(%r13)	# leave
+	chi	%r1,2
+	be	.Lservicecall-.LPG1(%r13)
+	lpswe	.Lwaitsclp-.LPG1(%r13)
 .Lsclph:
-	lh    %r1,.Lsccbr-.Lsccb(%r4)
-	chi   %r1,0x10			# 0x0010 is the sucess code
-	je    .Lprocsccb		# let's process the sccb
-	chi   %r1,0x1f0
-	bne   .Lfchunk-.LPG1(%r13)	# unhandled error code
-	c     %r2,.Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
-	bne   .Lfchunk-.LPG1(%r13)	# if no, give up
-	l     %r2,.Lrcp2-.LPG1(%r13)	# try with Read SCP
-	b     .Lservicecall-.LPG1(%r13)
+	lh	%r1,.Lsccbr-.Lsccb(%r4)
+	chi	%r1,0x10		# 0x0010 is the sucess code
+	je	.Lprocsccb		# let's process the sccb
+	chi	%r1,0x1f0
+	bne	.Lfchunk-.LPG1(%r13)	# unhandled error code
+	c	%r2,.Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
+	bne	.Lfchunk-.LPG1(%r13)	# if no, give up
+	l	%r2,.Lrcp2-.LPG1(%r13)	# try with Read SCP
+	b	.Lservicecall-.LPG1(%r13)
 .Lprocsccb:
-	lghi  %r1,0
-	icm   %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
-	jnz   .Lscnd
-	lg    %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one
+	lghi	%r1,0
+	icm	%r1,3,.Lscpincr1-.Lsccb(%r4)	# use this one if != 0
+	jnz	.Lscnd
+	lg	%r1,.Lscpincr2-.Lsccb(%r4)	# otherwise use this one
 .Lscnd:
-	xr    %r3,%r3			# same logic
-	ic    %r3,.Lscpa1-.Lsccb(%r4)
-	chi   %r3,0x00
-	jne   .Lcompmem
-	l     %r3,.Lscpa2-.Lsccb(%r4)
+	xr	%r3,%r3			# same logic
+	ic	%r3,.Lscpa1-.Lsccb(%r4)
+	chi	%r3,0x00
+	jne	.Lcompmem
+	l	%r3,.Lscpa2-.Lsccb(%r4)
 .Lcompmem:
-	mlgr  %r2,%r1			# mem in MB on 128-bit
-	l     %r1,.Lonemb-.LPG1(%r13)
-	mlgr  %r2,%r1			# mem size in bytes in %r3
-	b     .Lfchunk-.LPG1(%r13)
+	mlgr	%r2,%r1			# mem in MB on 128-bit
+	l	%r1,.Lonemb-.LPG1(%r13)
+	mlgr	%r2,%r1			# mem size in bytes in %r3
+	b	.Lfchunk-.LPG1(%r13)
 
-	.align 4
+	.align	4
 .Lpmask:
-	.byte 0
-	.align 8
+	.byte	0
+	.align	8
 .Lcr:
-	.quad 0x00  # place holder for cr0
+	.quad	0x00  # place holder for cr0
 .Lwaitsclp:
-	.quad  0x0102000180000000,.Lsclph
+	.quad	0x0102000180000000,.Lsclph
 .Lrcp:
-	.int 0x00120001 # Read SCP forced code
+	.int	0x00120001 # Read SCP forced code
 .Lrcp2:
-	.int 0x00020001 # Read SCP code
+	.int	0x00020001 # Read SCP code
 .Lonemb:
-	.int 0x100000
+	.int	0x100000
 
 .Lfchunk:
-					 # set program check new psw mask
-	mvc   __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
+					# set program check new psw mask
+	mvc	__LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
 
 #
 # find memory chunks.
 #
-	lgr   %r9,%r3			 # end of mem
-	larl  %r1,.Lchkmem               # set program check address
-	stg   %r1,__LC_PGM_NEW_PSW+8
-	la    %r1,1                      # test in increments of 128KB
-	sllg  %r1,%r1,17
-	larl  %r3,memory_chunk
-	slgr  %r4,%r4                    # set start of chunk to zero
-	slgr  %r5,%r5                    # set end of chunk to zero
-	slr  %r6,%r6			 # set access code to zero
-	la    %r10,MEMORY_CHUNKS	 # number of chunks
+	lgr	%r9,%r3			# end of mem
+	larl	%r1,.Lchkmem		# set program check address
+	stg	%r1,__LC_PGM_NEW_PSW+8
+	la	%r1,1			# test in increments of 128KB
+	sllg	%r1,%r1,17
+	larl	%r3,memory_chunk
+	slgr	%r4,%r4 		# set start of chunk to zero
+	slgr	%r5,%r5 		# set end of chunk to zero
+	slr	%r6,%r6			# set access code to zero
+	la	%r10,MEMORY_CHUNKS	# number of chunks
 .Lloop:
-	tprot 0(%r5),0			 # test protection of first byte
-	ipm   %r7
-	srl   %r7,28
-	clr   %r6,%r7			 # compare cc with last access code
-	je    .Lsame
-	j     .Lchkmem
+	tprot	0(%r5),0		# test protection of first byte
+	ipm	%r7
+	srl	%r7,28
+	clr	%r6,%r7			# compare cc with last access code
+	je	.Lsame
+	j	.Lchkmem
 .Lsame:
-	algr  %r5,%r1			 # add 128KB to end of chunk
-					 # no need to check here,
-	brc   12,.Lloop			 # this is the same chunk
-.Lchkmem:				 # > 16EB or tprot got a program check
-	clgr  %r4,%r5			 # chunk size > 0?
-	je    .Lchkloop
-	stg   %r4,0(%r3)		 # store start address of chunk
-	lgr   %r0,%r5
-	slgr  %r0,%r4
-	stg   %r0,8(%r3)		 # store size of chunk
-	st    %r6,20(%r3)		 # store type of chunk
-	la    %r3,24(%r3)
-	larl  %r8,memory_size
-	stg   %r5,0(%r8)                 # store memory size
-	ahi   %r10,-1			 # update chunk number
+	algr	%r5,%r1			# add 128KB to end of chunk
+					# no need to check here,
+	brc	12,.Lloop		# this is the same chunk
+.Lchkmem:				# > 16EB or tprot got a program check
+	clgr	%r4,%r5			# chunk size > 0?
+	je	.Lchkloop
+	stg	%r4,0(%r3)		# store start address of chunk
+	lgr	%r0,%r5
+	slgr	%r0,%r4
+	stg	%r0,8(%r3)		# store size of chunk
+	st	%r6,20(%r3)		# store type of chunk
+	la	%r3,24(%r3)
+	larl	%r8,memory_size
+	stg	%r5,0(%r8)		# store memory size
+	ahi	%r10,-1			# update chunk number
 .Lchkloop:
-	lr    %r6,%r7			 # set access code to last cc
+	lr	%r6,%r7			# set access code to last cc
 	# we got an exception or we're starting a new
 	# chunk , we must check if we should
 	# still try to find valid memory (if we detected
 	# the amount of available storage), and if we
 	# have chunks left
-	lghi  %r4,1
-	sllg  %r4,%r4,31
-	clgr  %r5,%r4
-	je    .Lhsaskip
-	xr    %r0, %r0
-	clgr  %r0, %r9			 # did we detect memory?
-	je    .Ldonemem			 # if not, leave
-	chi   %r10, 0			 # do we have chunks left?
-	je    .Ldonemem
+	lghi	%r4,1
+	sllg	%r4,%r4,31
+	clgr	%r5,%r4
+	je	.Lhsaskip
+	xr	%r0, %r0
+	clgr	%r0, %r9		# did we detect memory?
+	je	.Ldonemem		# if not, leave
+	chi	%r10, 0			# do we have chunks left?
+	je	.Ldonemem
 .Lhsaskip:
-	algr  %r5,%r1			 # add 128KB to end of chunk
-	lgr   %r4,%r5			 # potential new chunk
-	clgr  %r5,%r9			 # should we go on?
-	jl    .Lloop
-.Ldonemem:		
+	algr	%r5,%r1			# add 128KB to end of chunk
+	lgr	%r4,%r5			# potential new chunk
+	clgr	%r5,%r9			# should we go on?
+	jl	.Lloop
+.Ldonemem:
 
-	larl  %r12,machine_flags
+	larl	%r12,machine_flags
 #
 # find out if we are running under VM
 #
-        stidp  __LC_CPUID               # store cpuid
-	tm     __LC_CPUID,0xff          # running under VM ?
-	bno    0f-.LPG1(%r13)
-        oi     7(%r12),1                # set VM flag
-0:      lh     %r0,__LC_CPUID+4         # get cpu version
-        chi    %r0,0x7490               # running on a P/390 ?
-        bne    1f-.LPG1(%r13)
-        oi     7(%r12),4                # set P/390 flag
+	stidp	__LC_CPUID		# store cpuid
+	tm	__LC_CPUID,0xff 	# running under VM ?
+	bno	0f-.LPG1(%r13)
+	oi	7(%r12),1		# set VM flag
+0:	lh	%r0,__LC_CPUID+4	# get cpu version
+	chi	%r0,0x7490		# running on a P/390 ?
+	bne	1f-.LPG1(%r13)
+	oi	7(%r12),4		# set P/390 flag
 1:
 
 #
 # find out if we have the MVPG instruction
 #
-	la     %r1,0f-.LPG1(%r13)       # set program check address
-	stg    %r1,__LC_PGM_NEW_PSW+8
-	sgr    %r0,%r0
-	lghi   %r1,0
-	lghi   %r2,0
-	mvpg   %r1,%r2                  # test MVPG instruction
-	oi     7(%r12),16               # set MVPG flag
+	la	%r1,0f-.LPG1(%r13)	# set program check address
+	stg	%r1,__LC_PGM_NEW_PSW+8
+	sgr	%r0,%r0
+	lghi	%r1,0
+	lghi	%r2,0
+	mvpg	%r1,%r2 		# test MVPG instruction
+	oi	7(%r12),16		# set MVPG flag
 0:
 
 #
 # find out if the diag 0x44 works in 64 bit mode
 #
-	la     %r1,0f-.LPG1(%r13)	# set program check address
-	stg    %r1,__LC_PGM_NEW_PSW+8
-	diag   0,0,0x44			# test diag 0x44
-	oi     7(%r12),32		# set diag44 flag
-0:	
+	la	%r1,0f-.LPG1(%r13)	# set program check address
+	stg	%r1,__LC_PGM_NEW_PSW+8
+	diag	0,0,0x44		# test diag 0x44
+	oi	7(%r12),32		# set diag44 flag
+0:
 
 #
 # find out if we have the IDTE instruction
 #
-	la     %r1,0f-.LPG1(%r13)	# set program check address
-	stg    %r1,__LC_PGM_NEW_PSW+8
+	la	%r1,0f-.LPG1(%r13)	# set program check address
+	stg	%r1,__LC_PGM_NEW_PSW+8
 	.long	0xb2b10000		# store facility list
 	tm	0xc8,0x08		# check bit for clearing-by-ASCE
 	bno	0f-.LPG1(%r13)
@@ -263,45 +263,45 @@
 	oi	6(%r12),2		# set MVCOS flag
 1:
 
-        lpswe .Lentry-.LPG1(13)         # jump to _stext in primary-space,
-                                        # virtual and never return ...
-        .align 16
-.Lentry:.quad  0x0000000180000000,_stext
-.Lctl:  .quad  0x04b50002               # cr0: various things
-        .quad  0                        # cr1: primary space segment table
-        .quad  .Lduct                   # cr2: dispatchable unit control table
-        .quad  0                        # cr3: instruction authorization
-        .quad  0                        # cr4: instruction authorization
-        .quad  0xffffffffffffffff       # cr5: primary-aste origin
-        .quad  0                        # cr6:  I/O interrupts
-        .quad  0                        # cr7:  secondary space segment table
-        .quad  0                        # cr8:  access registers translation
-        .quad  0                        # cr9:  tracing off
-        .quad  0                        # cr10: tracing off
-        .quad  0                        # cr11: tracing off
-        .quad  0                        # cr12: tracing off
-        .quad  0                        # cr13: home space segment table
-        .quad  0xc0000000               # cr14: machine check handling off
-        .quad  0                        # cr15: linkage stack operations
-.Lduct: .long 0,0,0,0,0,0,0,0
-	.long 0,0,0,0,0,0,0,0
-.Lpcmsk:.quad  0x0000000180000000
+	lpswe	.Lentry-.LPG1(13)	# jump to _stext in primary-space,
+					# virtual and never return ...
+	.align	16
+.Lentry:.quad	0x0000000180000000,_stext
+.Lctl:	.quad	0x04b50002		# cr0: various things
+	.quad	0			# cr1: primary space segment table
+	.quad	.Lduct			# cr2: dispatchable unit control table
+	.quad	0			# cr3: instruction authorization
+	.quad	0			# cr4: instruction authorization
+	.quad	0xffffffffffffffff	# cr5: primary-aste origin
+	.quad	0			# cr6:	I/O interrupts
+	.quad	0			# cr7:	secondary space segment table
+	.quad	0			# cr8:	access registers translation
+	.quad	0			# cr9:	tracing off
+	.quad	0			# cr10: tracing off
+	.quad	0			# cr11: tracing off
+	.quad	0			# cr12: tracing off
+	.quad	0			# cr13: home space segment table
+	.quad	0xc0000000		# cr14: machine check handling off
+	.quad	0			# cr15: linkage stack operations
+.Lduct: .long	0,0,0,0,0,0,0,0
+	.long	0,0,0,0,0,0,0,0
+.Lpcmsk:.quad	0x0000000180000000
 .L4malign:.quad 0xffffffffffc00000
-.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
-.Lnop:	.long  0x07000700
+.Lscan2g:.quad	0x80000000 + 0x20000 - 8	# 2GB + 128K - 8
+.Lnop:	.long	0x07000700
 .Lparmaddr:
 	.quad	PARMAREA
 
-	.globl ipl_schib
+	.globl	ipl_schib
 ipl_schib:
 	.rept 13
 	.long 0
 	.endr
 
-	.globl ipl_flags
+	.globl	ipl_flags
 ipl_flags:
-	.long 0
-	.globl ipl_devno
+	.long	0
+	.globl	ipl_devno
 ipl_devno:
 	.word 0
 
@@ -309,47 +309,47 @@
 .globl s390_readinfo_sccb
 s390_readinfo_sccb:
 .Lsccb:
-	.hword 0x1000			# length, one page
-	.byte 0x00,0x00,0x00
-	.byte 0x80			# variable response bit set
+	.hword	0x1000			# length, one page
+	.byte	0x00,0x00,0x00
+	.byte	0x80			# variable response bit set
 .Lsccbr:
-	.hword 0x00			# response code
+	.hword	0x00			# response code
 .Lscpincr1:
-	.hword 0x00
+	.hword	0x00
 .Lscpa1:
-	.byte 0x00
-	.fill 89,1,0
+	.byte	0x00
+	.fill	89,1,0
 .Lscpa2:
-	.int 0x00
+	.int	0x00
 .Lscpincr2:
-	.quad 0x00
-	.fill 3984,1,0
+	.quad	0x00
+	.fill	3984,1,0
 	.org	0x13000
 
 #ifdef CONFIG_SHARED_KERNEL
-	.org   0x100000
+	.org	0x100000
 #endif
-	
+
 #
 # startup-code, running in absolute addressing mode
 #
-        .globl _stext
-_stext:	basr  %r13,0                    # get base
+	.globl	_stext
+_stext:	basr	%r13,0			# get base
 .LPG3:
 # check control registers
-        stctg  %c0,%c15,0(%r15)
-	oi     6(%r15),0x40             # enable sigp emergency signal
-	oi     4(%r15),0x10             # switch on low address proctection
-        lctlg  %c0,%c15,0(%r15)
+	stctg	%c0,%c15,0(%r15)
+	oi	6(%r15),0x40		# enable sigp emergency signal
+	oi	4(%r15),0x10		# switch on low address proctection
+	lctlg	%c0,%c15,0(%r15)
 
-        lam    0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
-        brasl  %r14,start_kernel        # go to C code
+	lam	0,15,.Laregs-.LPG3(%r13)	# load acrs needed by uaccess
+	brasl	%r14,start_kernel	# go to C code
 #
 # We returned from start_kernel ?!? PANIK
 #
-        basr  %r13,0
-	lpswe .Ldw-.(%r13)           # load disabled wait psw
+	basr	%r13,0
+	lpswe	.Ldw-.(%r13)		# load disabled wait psw
 
-            .align 8
-.Ldw:       .quad  0x0002000180000000,0x0000000000000000
-.Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.align	8
+.Ldw:	.quad	0x0002000180000000,0x0000000000000000
+.Laregs:.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 6555cc4..1f5e782 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -120,24 +120,15 @@
 
 static int diag308(unsigned long subcode, void *addr)
 {
-	register unsigned long _addr asm("0") = (unsigned long)addr;
+	register unsigned long _addr asm("0") = (unsigned long) addr;
 	register unsigned long _rc asm("1") = 0;
 
-	asm volatile (
-		"   diag %0,%2,0x308\n"
-		"0: \n"
-		".section __ex_table,\"a\"\n"
-#ifdef CONFIG_64BIT
-		"   .align 8\n"
-		"   .quad 0b, 0b\n"
-#else
-		"   .align 4\n"
-		"   .long 0b, 0b\n"
-#endif
-		".previous\n"
+	asm volatile(
+		"	diag	%0,%2,0x308\n"
+		"0:\n"
+		EX_TABLE(0b,0b)
 		: "+d" (_addr), "+d" (_rc)
-		: "d" (subcode) : "cc", "memory" );
-
+		: "d" (subcode) : "cc", "memory");
 	return _rc;
 }
 
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index d3cbfa3..6603fbb 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -45,7 +45,7 @@
 #include <asm/irq.h>
 #include <asm/timer.h>
 
-asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
 
 /*
  * Return saved PC of a blocked thread. used in kernel/sched.
@@ -177,7 +177,8 @@
 
 extern void kernel_thread_starter(void);
 
-__asm__(".align 4\n"
+asm(
+	".align 4\n"
 	"kernel_thread_starter:\n"
 	"    la    2,0(10)\n"
 	"    basr  14,9\n"
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index 4562cdb..0340477 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -32,58 +32,58 @@
 		st	%r13, __LC_PSW_SAVE_AREA+4
 
 		lctl	%c6,%c6,.Lall-.Lpg0(%r13)
-                lr      %r1,%r2
-        	mvc     __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
-                stsch   .Lschib-.Lpg0(%r13)                                    
-	        oi      .Lschib+5-.Lpg0(%r13),0x84 
-.Lecs:  	xi      .Lschib+27-.Lpg0(%r13),0x01 
-        	msch    .Lschib-.Lpg0(%r13) 
-                lhi     %r0,5
-.Lssch:		ssch	.Liplorb-.Lpg0(%r13)           
+		lr	%r1,%r2
+		mvc	__LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
+		stsch	.Lschib-.Lpg0(%r13)
+		oi	.Lschib+5-.Lpg0(%r13),0x84
+.Lecs:  	xi	.Lschib+27-.Lpg0(%r13),0x01
+		msch	.Lschib-.Lpg0(%r13)
+		lhi	%r0,5
+.Lssch:		ssch	.Liplorb-.Lpg0(%r13)
 		jz	.L001
-                brct    %r0,.Lssch  
+		brct	%r0,.Lssch
 		bas	%r14,.Ldisab-.Lpg0(%r13)
-.L001:		mvc	__LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)	
-.Ltpi:		lpsw	.Lwaitpsw-.Lpg0(%r13)          
+.L001:		mvc	__LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)
+.Ltpi:		lpsw	.Lwaitpsw-.Lpg0(%r13)
 .Lcont:		c	%r1,__LC_SUBCHANNEL_ID
 		jnz	.Ltpi
 		clc	__LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
 		jnz	.Ltpi
-		tsch	.Liplirb-.Lpg0(%r13)           
+		tsch	.Liplirb-.Lpg0(%r13)
 		tm	.Liplirb+9-.Lpg0(%r13),0xbf
-                jz      .L002
-                bas     %r14,.Ldisab-.Lpg0(%r13)    
-.L002:		tm	.Liplirb+8-.Lpg0(%r13),0xf3    
-                jz      .L003
-                bas     %r14,.Ldisab-.Lpg0(%r13)	
+		jz	.L002
+		bas	%r14,.Ldisab-.Lpg0(%r13)
+.L002:		tm	.Liplirb+8-.Lpg0(%r13),0xf3
+		jz	.L003
+		bas	%r14,.Ldisab-.Lpg0(%r13)
 .L003:		spx	.Lnull-.Lpg0(%r13)
-		st 	%r1,__LC_SUBCHANNEL_ID
-                lpsw 	0
-		sigp    0,0,0(6)               
-.Ldisab:	st      %r14,.Ldispsw+4-.Lpg0(%r13)
+		st	%r1,__LC_SUBCHANNEL_ID
+		lpsw	0
+		sigp	0,0,0(6)
+.Ldisab:	st	%r14,.Ldispsw+4-.Lpg0(%r13)
 		lpsw	.Ldispsw-.Lpg0(%r13)
-                .align 	8
+		.align	8
 .Lclkcmp:	.quad	0x0000000000000000
 .Lall:		.long	0xff000000
-.Lnull:		.long   0x00000000
+.Lnull:		.long	0x00000000
 .Lctlsave1:	.long	0x00000000
 .Lctlsave2:	.long	0x00000000
-                .align 	8
-.Lnewpsw:	.long   0x00080000,0x80000000+.Lpg1
-.Lpcnew:  	.long   0x00080000,0x80000000+.Lecs
-.Lionew:	.long   0x00080000,0x80000000+.Lcont
+		.align	8
+.Lnewpsw:	.long	0x00080000,0x80000000+.Lpg1
+.Lpcnew:	.long	0x00080000,0x80000000+.Lecs
+.Lionew:	.long	0x00080000,0x80000000+.Lcont
 .Lwaitpsw:	.long	0x020a0000,0x00000000+.Ltpi
-.Ldispsw:	.long   0x000a0000,0x00000000
-.Liplccws:	.long   0x02000000,0x60000018
-		.long   0x08000008,0x20000001
+.Ldispsw:	.long	0x000a0000,0x00000000
+.Liplccws:	.long	0x02000000,0x60000018
+		.long	0x08000008,0x20000001
 .Liplorb:	.long	0x0049504c,0x0040ff80
 		.long	0x00000000+.Liplccws
-.Lschib:        .long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
+.Lschib:	.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
 .Liplirb:	.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
@@ -92,6 +92,3 @@
 		.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
-	
-
-	
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index 95bd1e2..de74350 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -4,7 +4,7 @@
  *  S390 version
  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
-	         Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+		 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  */
 
 #include <asm/lowcore.h>
@@ -32,46 +32,46 @@
 		stctg	%c0,%c0,.Lregsave-.Lpg0(%r13)
 		ni	.Lregsave+4-.Lpg0(%r13),0xef
 		lctlg	%c0,%c0,.Lregsave-.Lpg0(%r13)
-                lgr     %r1,%r2
-        	mvc     __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
-                stsch   .Lschib-.Lpg0(%r13)                                    
-	        oi      .Lschib+5-.Lpg0(%r13),0x84 
-.Lecs:  	xi      .Lschib+27-.Lpg0(%r13),0x01 
-        	msch    .Lschib-.Lpg0(%r13) 
-	        lghi    %r0,5
-.Lssch:		ssch	.Liplorb-.Lpg0(%r13)           
+		lgr	%r1,%r2
+		mvc	__LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
+		stsch	.Lschib-.Lpg0(%r13)
+		oi	.Lschib+5-.Lpg0(%r13),0x84
+.Lecs:  	xi	.Lschib+27-.Lpg0(%r13),0x01
+		msch	.Lschib-.Lpg0(%r13)
+		lghi	%r0,5
+.Lssch:		ssch	.Liplorb-.Lpg0(%r13)
 		jz	.L001
-		brct    %r0,.Lssch   
+		brct	%r0,.Lssch
 		bas	%r14,.Ldisab-.Lpg0(%r13)
-.L001:		mvc	__LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13)	
-.Ltpi:		lpswe	.Lwaitpsw-.Lpg0(%r13)          
+.L001:		mvc	__LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13)
+.Ltpi:		lpswe	.Lwaitpsw-.Lpg0(%r13)
 .Lcont:		c	%r1,__LC_SUBCHANNEL_ID
 		jnz	.Ltpi
 		clc	__LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
 		jnz	.Ltpi
-		tsch	.Liplirb-.Lpg0(%r13)           
+		tsch	.Liplirb-.Lpg0(%r13)
 		tm	.Liplirb+9-.Lpg0(%r13),0xbf
-                jz      .L002
-                bas     %r14,.Ldisab-.Lpg0(%r13)    
-.L002:		tm	.Liplirb+8-.Lpg0(%r13),0xf3    
-                jz      .L003
-                bas     %r14,.Ldisab-.Lpg0(%r13)	
+		jz	.L002
+		bas	%r14,.Ldisab-.Lpg0(%r13)
+.L002:		tm	.Liplirb+8-.Lpg0(%r13),0xf3
+		jz	.L003
+		bas	%r14,.Ldisab-.Lpg0(%r13)
 .L003:		spx	.Lnull-.Lpg0(%r13)
-		st 	%r1,__LC_SUBCHANNEL_ID
-                lhi     %r1,0            # mode 0 = esa
-                slr     %r0,%r0          # set cpuid to zero
-                sigp    %r1,%r0,0x12     # switch to esa mode
-                lpsw 	0
-.Ldisab:	sll    %r14,1
-		srl    %r14,1            # need to kill hi bit to avoid specification exceptions.
-		st     %r14,.Ldispsw+12-.Lpg0(%r13)
+		st	%r1,__LC_SUBCHANNEL_ID
+		lhi	%r1,0		 # mode 0 = esa
+		slr	%r0,%r0 	 # set cpuid to zero
+		sigp	%r1,%r0,0x12	 # switch to esa mode
+		lpsw	0
+.Ldisab:	sll	%r14,1
+		srl	%r14,1		 # need to kill hi bit to avoid specification exceptions.
+		st	%r14,.Ldispsw+12-.Lpg0(%r13)
 		lpswe	.Ldispsw-.Lpg0(%r13)
-                .align 	8
+		.align	8
 .Lclkcmp:	.quad	0x0000000000000000
 .Lall:		.quad	0x00000000ff000000
 .Lregsave:	.quad	0x0000000000000000
-.Lnull:		.long   0x0000000000000000
-                .align 	16
+.Lnull:		.long	0x0000000000000000
+		.align	16
 /*
  * These addresses have to be 31 bit otherwise
  * the sigp will throw a specifcation exception
@@ -81,26 +81,26 @@
  * 31bit lpswe instruction a fact they appear to have
  * ommited from the pop.
  */
-.Lnewpsw:	.quad   0x0000000080000000
-		.quad   .Lpg1
-.Lpcnew:	.quad   0x0000000080000000
-	  	.quad   .Lecs
-.Lionew:	.quad   0x0000000080000000
-		.quad   .Lcont
+.Lnewpsw:	.quad	0x0000000080000000
+		.quad	.Lpg1
+.Lpcnew:	.quad	0x0000000080000000
+		.quad	.Lecs
+.Lionew:	.quad	0x0000000080000000
+		.quad	.Lcont
 .Lwaitpsw:	.quad	0x0202000080000000
-		.quad   .Ltpi
-.Ldispsw:	.quad   0x0002000080000000
-		.quad   0x0000000000000000
-.Liplccws:	.long   0x02000000,0x60000018
-		.long   0x08000008,0x20000001
+		.quad	.Ltpi
+.Ldispsw:	.quad	0x0002000080000000
+		.quad	0x0000000000000000
+.Liplccws:	.long	0x02000000,0x60000018
+		.long	0x08000008,0x20000001
 .Liplorb:	.long	0x0049504c,0x0040ff80
 		.long	0x00000000+.Liplccws
-.Lschib:        .long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
-		.long   0x00000000,0x00000000
+.Lschib:	.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
 .Liplirb:	.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
@@ -109,4 +109,3 @@
 		.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
 		.long	0x00000000,0x00000000
-	
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
index 2a25ec7..f9899ff 100644
--- a/arch/s390/kernel/relocate_kernel.S
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -3,7 +3,7 @@
  *
  * (C) Copyright IBM Corp. 2005
  *
- * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ * Author(s): Rolf Adelsberger,
  *	      Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  */
@@ -24,14 +24,14 @@
 	.text
 	.globl		relocate_kernel
 	relocate_kernel:
-		basr	%r13,0		#base address
+		basr	%r13,0		# base address
 	.base:
-		stnsm	sys_msk-.base(%r13),0xf8	#disable DAT and IRQ (external)
-		spx	zero64-.base(%r13)	#absolute addressing mode
+		stnsm	sys_msk-.base(%r13),0xf8	# disable DAT and IRQ (external)
+		spx	zero64-.base(%r13)	# absolute addressing mode
 		stctl	%c0,%c15,ctlregs-.base(%r13)
 		stm	%r0,%r15,gprregs-.base(%r13)
 		la	%r1,load_psw-.base(%r13)
-		mvc     0(8,%r0),0(%r1)
+		mvc	0(8,%r0),0(%r1)
 		la	%r0,.back-.base(%r13)
 		st	%r0,4(%r0)
 		oi	4(%r0),0x80
@@ -51,50 +51,50 @@
 	.back_pgm:
 		lm	%r0,%r15,gprregs-.base(%r13)
 	.start_reloc:
-		lhi	%r10,-1		#preparing the mask
-		sll	%r10,12		#shift it such that it becomes 0xf000
+		lhi	%r10,-1		# preparing the mask
+		sll	%r10,12		# shift it such that it becomes 0xf000
 	.top:
-		lhi	%r7,4096	#load PAGE_SIZE in r7
-		lhi	%r9,4096	#load PAGE_SIZE in r9
-		l	%r5,0(%r2)	#read another word for indirection page
-		ahi	%r2,4		#increment pointer
-		tml	%r5,0x1		#is it a destination page?
-		je	.indir_check	#NO, goto "indir_check"
-		lr	%r6,%r5		#r6 = r5
-		nr	%r6,%r10	#mask it out and...
-		j	.top		#...next iteration
+		lhi	%r7,4096	# load PAGE_SIZE in r7
+		lhi	%r9,4096	# load PAGE_SIZE in r9
+		l	%r5,0(%r2)	# read another word for indirection page
+		ahi	%r2,4		# increment pointer
+		tml	%r5,0x1		# is it a destination page?
+		je	.indir_check	# NO, goto "indir_check"
+		lr	%r6,%r5		# r6 = r5
+		nr	%r6,%r10	# mask it out and...
+		j	.top		# ...next iteration
 	.indir_check:
-		tml	%r5,0x2		#is it a indirection page?
-		je	.done_test	#NO, goto "done_test"
-		nr	%r5,%r10	#YES, mask out,
-		lr	%r2,%r5		#move it into the right register,
-		j	.top		#and read next...
+		tml	%r5,0x2		# is it a indirection page?
+		je	.done_test	# NO, goto "done_test"
+		nr	%r5,%r10	# YES, mask out,
+		lr	%r2,%r5		# move it into the right register,
+		j	.top		# and read next...
 	.done_test:
-		tml	%r5,0x4		#is it the done indicator?
-		je	.source_test	#NO! Well, then it should be the source indicator...
-		j	.done		#ok, lets finish it here...
+		tml	%r5,0x4		# is it the done indicator?
+		je	.source_test	# NO! Well, then it should be the source indicator...
+		j	.done		# ok, lets finish it here...
 	.source_test:
-		tml	%r5,0x8		#it should be a source indicator...
-		je	.top		#NO, ignore it...
-		lr	%r8,%r5		#r8 = r5
-		nr	%r8,%r10	#masking
-	0:	mvcle	%r6,%r8,0x0	#copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+		tml	%r5,0x8		# it should be a source indicator...
+		je	.top		# NO, ignore it...
+		lr	%r8,%r5		# r8 = r5
+		nr	%r8,%r10	# masking
+	0:	mvcle	%r6,%r8,0x0	# copy PAGE_SIZE bytes from r8 to r6 - pad with 0
 		jo	0b
 		j	.top
 	.done:
-		sr	%r0,%r0		#clear register r0
-		la	%r4,load_psw-.base(%r13)	#load psw-address into the register
-		o	%r3,4(%r4)	#or load address into psw
+		sr	%r0,%r0		# clear register r0
+		la	%r4,load_psw-.base(%r13)	# load psw-address into the register
+		o	%r3,4(%r4)	# or load address into psw
 		st	%r3,4(%r4)
-		mvc	0(8,%r0),0(%r4)	#copy psw to absolute address 0
+		mvc	0(8,%r0),0(%r4)	# copy psw to absolute address 0
 		tm	have_diag308-.base(%r13),0x01
 		jno	.no_diag308
 		diag	%r0,%r0,0x308
 	.no_diag308:
-		sr	%r1,%r1		#clear %r1
-		sr	%r2,%r2		#clear %r2
-		sigp	%r1,%r2,0x12	#set cpuid to zero
-		lpsw	0		#hopefully start new kernel...
+		sr	%r1,%r1		# clear %r1
+		sr	%r2,%r2		# clear %r2
+		sigp	%r1,%r2,0x12	# set cpuid to zero
+		lpsw	0		# hopefully start new kernel...
 
 		.align	8
 	zero64:
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
index 8cdb86e..4fb4430 100644
--- a/arch/s390/kernel/relocate_kernel64.S
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -3,7 +3,7 @@
  *
  * (C) Copyright IBM Corp. 2005
  *
- * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ * Author(s): Rolf Adelsberger,
  *	      Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  */
@@ -25,10 +25,10 @@
 	.text
 	.globl		relocate_kernel
 	relocate_kernel:
-		basr	%r13,0		#base address
+		basr	%r13,0		# base address
 	.base:
-		stnsm	sys_msk-.base(%r13),0xf8	#disable DAT and IRQs
-		spx	zero64-.base(%r13)	#absolute addressing mode
+		stnsm	sys_msk-.base(%r13),0xf8	# disable DAT and IRQs
+		spx	zero64-.base(%r13)	# absolute addressing mode
 		stctg	%c0,%c15,ctlregs-.base(%r13)
 		stmg	%r0,%r15,gprregs-.base(%r13)
 		lghi	%r0,3
@@ -37,16 +37,16 @@
 		la	%r0,.back_pgm-.base(%r13)
 		stg	%r0,0x1d8(%r0)
 		la	%r1,load_psw-.base(%r13)
-		mvc     0(8,%r0),0(%r1)
+		mvc	0(8,%r0),0(%r1)
 		la	%r0,.back-.base(%r13)
 		st	%r0,4(%r0)
 		oi	4(%r0),0x80
 		lghi	%r0,0
 		diag	%r0,%r0,0x308
 	.back:
-		lhi	%r1,1		#mode 1 = esame
-		sigp	%r1,%r0,0x12	#switch to esame mode
-		sam64			#switch to 64 bit addressing mode
+		lhi	%r1,1		# mode 1 = esame
+		sigp	%r1,%r0,0x12	# switch to esame mode
+		sam64			# switch to 64 bit addressing mode
 		basr	%r13,0
 	.back_base:
 		oi	have_diag308-.back_base(%r13),0x01
@@ -56,50 +56,50 @@
 	.back_pgm:
 		lmg	%r0,%r15,gprregs-.base(%r13)
 	.top:
-		lghi	%r7,4096	#load PAGE_SIZE in r7
-		lghi	%r9,4096	#load PAGE_SIZE in r9
-		lg	%r5,0(%r2)	#read another word for indirection page
-		aghi	%r2,8		#increment pointer
-		tml	%r5,0x1		#is it a destination page?
-		je	.indir_check	#NO, goto "indir_check"
-		lgr	%r6,%r5		#r6 = r5
-		nill	%r6,0xf000	#mask it out and...
-		j	.top		#...next iteration
+		lghi	%r7,4096	# load PAGE_SIZE in r7
+		lghi	%r9,4096	# load PAGE_SIZE in r9
+		lg	%r5,0(%r2)	# read another word for indirection page
+		aghi	%r2,8		# increment pointer
+		tml	%r5,0x1		# is it a destination page?
+		je	.indir_check	# NO, goto "indir_check"
+		lgr	%r6,%r5		# r6 = r5
+		nill	%r6,0xf000	# mask it out and...
+		j	.top		# ...next iteration
 	.indir_check:
-		tml     %r5,0x2		#is it a indirection page?
-		je      .done_test	#NO, goto "done_test"
-		nill    %r5,0xf000	#YES, mask out,
-		lgr     %r2,%r5		#move it into the right register,
-		j       .top		#and read next...
+		tml	%r5,0x2		# is it a indirection page?
+		je	.done_test	# NO, goto "done_test"
+		nill	%r5,0xf000	# YES, mask out,
+		lgr	%r2,%r5		# move it into the right register,
+		j	.top		# and read next...
 	.done_test:
-		tml     %r5,0x4		#is it the done indicator?
-		je      .source_test	#NO! Well, then it should be the source indicator...
-		j       .done		#ok, lets finish it here...
+		tml	%r5,0x4		# is it the done indicator?
+		je	.source_test	# NO! Well, then it should be the source indicator...
+		j	.done		# ok, lets finish it here...
 	.source_test:
-		tml     %r5,0x8		#it should be a source indicator...
-		je      .top		#NO, ignore it...
-		lgr     %r8,%r5		#r8 = r5
-		nill    %r8,0xf000	#masking
-	0:	mvcle   %r6,%r8,0x0	#copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+		tml	%r5,0x8		# it should be a source indicator...
+		je	.top		# NO, ignore it...
+		lgr	%r8,%r5		# r8 = r5
+		nill	%r8,0xf000	# masking
+	0:	mvcle	%r6,%r8,0x0	# copy PAGE_SIZE bytes from r8 to r6 - pad with 0
 		jo	0b
-		j       .top
+		j	.top
 	.done:
-		sgr     %r0,%r0		#clear register r0
-		la      %r4,load_psw-.base(%r13)	#load psw-address into the register
-		o	%r3,4(%r4)	#or load address into psw
+		sgr	%r0,%r0		# clear register r0
+		la	%r4,load_psw-.base(%r13)	# load psw-address into the register
+		o	%r3,4(%r4)	# or load address into psw
 		st	%r3,4(%r4)
-		mvc     0(8,%r0),0(%r4)	#copy psw to absolute address 0
+		mvc	0(8,%r0),0(%r4)	# copy psw to absolute address 0
 		tm	have_diag308-.base(%r13),0x01
 		jno	.no_diag308
 		diag	%r0,%r0,0x308
 	.no_diag308:
-		sam31			#31 bit mode
-		sr      %r1,%r1		#erase register r1
-		sr      %r2,%r2		#erase register r2
-		sigp    %r1,%r2,0x12	#set cpuid to zero
-		lpsw    0		#hopefully start new kernel...
+		sam31			# 31 bit mode
+		sr	%r1,%r1		# erase register r1
+		sr	%r2,%r2		# erase register r2
+		sigp	%r1,%r2,0x12	# set cpuid to zero
+		lpsw	0		# hopefully start new kernel...
 
-	        .align	8
+		.align	8
 	zero64:
 		.quad	0
 	load_psw:
diff --git a/arch/s390/kernel/semaphore.c b/arch/s390/kernel/semaphore.c
index 8dfb690..191303f 100644
--- a/arch/s390/kernel/semaphore.c
+++ b/arch/s390/kernel/semaphore.c
@@ -26,17 +26,17 @@
 {
 	int old_val, new_val;
 
-        __asm__ __volatile__("   l     %0,0(%3)\n"
-                             "0: ltr   %1,%0\n"
-			     "   jhe   1f\n"
-			     "   lhi   %1,0\n"
-			     "1: ar    %1,%4\n"
-                             "   cs    %0,%1,0(%3)\n"
-                             "   jl    0b\n"
-                             : "=&d" (old_val), "=&d" (new_val),
-			       "=m" (sem->count)
-			     : "a" (&sem->count), "d" (incr), "m" (sem->count)
-			     : "cc" );
+	asm volatile(
+		"	l	%0,0(%3)\n"
+		"0:	ltr	%1,%0\n"
+		"	jhe	1f\n"
+		"	lhi	%1,0\n"
+		"1:	ar	%1,%4\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b\n"
+		: "=&d" (old_val), "=&d" (new_val), "=m" (sem->count)
+		: "a" (&sem->count), "d" (incr), "m" (sem->count)
+		: "cc");
 	return old_val;
 }
 
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index e3d9325..a21cfbb 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -101,7 +101,7 @@
         /*
          * Store processor id in lowcore (used e.g. in timer_interrupt)
          */
-        asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
+	asm volatile("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
         S390_lowcore.cpu_data.cpu_addr = addr;
 
         /*
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index b2e6f4c..a8e6199 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -63,7 +63,7 @@
 static void smp_ext_bitcall_others(ec_bit_sig);
 
 /*
- * Structure and data for smp_call_function(). This is designed to minimise
+5B * Structure and data for smp_call_function(). This is designed to minimise
  * static memory requirements. It also looks cleaner.
  */
 static DEFINE_SPINLOCK(call_lock);
@@ -418,59 +418,49 @@
 /*
  * parameter area for the set/clear control bit callbacks
  */
-typedef struct
-{
-	__u16 start_ctl;
-	__u16 end_ctl;
+struct ec_creg_mask_parms {
 	unsigned long orvals[16];
 	unsigned long andvals[16];
-} ec_creg_mask_parms;
+};
 
 /*
  * callback for setting/clearing control bits
  */
 void smp_ctl_bit_callback(void *info) {
-	ec_creg_mask_parms *pp;
+	struct ec_creg_mask_parms *pp = info;
 	unsigned long cregs[16];
 	int i;
 	
-	pp = (ec_creg_mask_parms *) info;
-	__ctl_store(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
-	for (i = pp->start_ctl; i <= pp->end_ctl; i++)
+	__ctl_store(cregs, 0, 15);
+	for (i = 0; i <= 15; i++)
 		cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i];
-	__ctl_load(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
+	__ctl_load(cregs, 0, 15);
 }
 
 /*
  * Set a bit in a control register of all cpus
  */
-void smp_ctl_set_bit(int cr, int bit) {
-        ec_creg_mask_parms parms;
+void smp_ctl_set_bit(int cr, int bit)
+{
+	struct ec_creg_mask_parms parms;
 
-	parms.start_ctl = cr;
-	parms.end_ctl = cr;
+	memset(&parms.orvals, 0, sizeof(parms.orvals));
+	memset(&parms.andvals, 0xff, sizeof(parms.andvals));
 	parms.orvals[cr] = 1 << bit;
-	parms.andvals[cr] = -1L;
-	preempt_disable();
-	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_set_bit(cr, bit);
-	preempt_enable();
+	on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 /*
  * Clear a bit in a control register of all cpus
  */
-void smp_ctl_clear_bit(int cr, int bit) {
-        ec_creg_mask_parms parms;
+void smp_ctl_clear_bit(int cr, int bit)
+{
+	struct ec_creg_mask_parms parms;
 
-	parms.start_ctl = cr;
-	parms.end_ctl = cr;
-	parms.orvals[cr] = 0;
+	memset(&parms.orvals, 0, sizeof(parms.orvals));
+	memset(&parms.andvals, 0xff, sizeof(parms.andvals));
 	parms.andvals[cr] = ~(1L << bit);
-	preempt_disable();
-	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_clear_bit(cr, bit);
-	preempt_enable();
+	on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 /*
@@ -650,9 +640,9 @@
 	sf->gprs[9] = (unsigned long) sf;
 	cpu_lowcore->save_area[15] = (unsigned long) sf;
 	__ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
-	__asm__ __volatile__("stam  0,15,0(%0)"
-			     : : "a" (&cpu_lowcore->access_regs_save_area)
-			     : "memory");
+	asm volatile(
+		"	stam	0,15,0(%0)"
+		: : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
 	cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
         cpu_lowcore->current_task = (unsigned long) idle;
         cpu_lowcore->cpu_data.cpu_nr = cpu;
@@ -708,7 +698,7 @@
 __cpu_disable(void)
 {
 	unsigned long flags;
-	ec_creg_mask_parms cr_parms;
+	struct ec_creg_mask_parms cr_parms;
 	int cpu = smp_processor_id();
 
 	spin_lock_irqsave(&smp_reserve_lock, flags);
@@ -724,30 +714,21 @@
 		pfault_fini();
 #endif
 
-	/* disable all external interrupts */
+	memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals));
+	memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals));
 
-	cr_parms.start_ctl = 0;
-	cr_parms.end_ctl = 0;
+	/* disable all external interrupts */
 	cr_parms.orvals[0] = 0;
 	cr_parms.andvals[0] = ~(1<<15 | 1<<14 | 1<<13 | 1<<12 |
 				1<<11 | 1<<10 | 1<< 6 | 1<< 4);
-	smp_ctl_bit_callback(&cr_parms);
-
 	/* disable all I/O interrupts */
-
-	cr_parms.start_ctl = 6;
-	cr_parms.end_ctl = 6;
 	cr_parms.orvals[6] = 0;
 	cr_parms.andvals[6] = ~(1<<31 | 1<<30 | 1<<29 | 1<<28 |
 				1<<27 | 1<<26 | 1<<25 | 1<<24);
-	smp_ctl_bit_callback(&cr_parms);
-
 	/* disable most machine checks */
-
-	cr_parms.start_ctl = 14;
-	cr_parms.end_ctl = 14;
 	cr_parms.orvals[14] = 0;
 	cr_parms.andvals[14] = ~(1<<28 | 1<<27 | 1<<26 | 1<<25 | 1<<24);
+
 	smp_ctl_bit_callback(&cr_parms);
 
 	spin_unlock_irqrestore(&smp_reserve_lock, flags);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 74e6178..abab42e 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -166,7 +166,7 @@
 void account_ticks(struct pt_regs *regs)
 {
 	__u64 tmp;
-	__u32 ticks, xticks;
+	__u32 ticks;
 
 	/* Calculate how many ticks have passed. */
 	if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
@@ -204,6 +204,7 @@
 	 */
 	write_seqlock(&xtime_lock);
 	if (S390_lowcore.jiffy_timer > xtime_cc) {
+		__u32 xticks;
 		tmp = S390_lowcore.jiffy_timer - xtime_cc;
 		if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
 			xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
@@ -212,13 +213,11 @@
 			xticks = 1;
 			xtime_cc += CLK_TICKS_PER_JIFFY;
 		}
-		while (xticks--)
-			do_timer(regs);
+		do_timer(xticks);
 	}
 	write_sequnlock(&xtime_lock);
 #else
-	for (xticks = ticks; xticks > 0; xticks--)
-		do_timer(regs);
+	do_timer(ticks);
 #endif
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -351,10 +350,12 @@
 	int cc;
 
         /* kick the TOD clock */
-        asm volatile ("STCK 0(%1)\n\t"
-                      "IPM  %0\n\t"
-                      "SRL  %0,28" : "=r" (cc) : "a" (&init_timer_cc) 
-				   : "memory", "cc");
+	asm volatile(
+		"	stck	0(%2)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (cc), "=m" (init_timer_cc)
+		: "a" (&init_timer_cc) : "cc");
         switch (cc) {
         case 0: /* clock in set state: all is fine */
                 break;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index c4982c9..3eb4fab 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -597,8 +597,7 @@
 		local_irq_enable();
 
 	if (MACHINE_HAS_IEEE)
-		__asm__ volatile ("stfpc %0\n\t" 
-				  : "=m" (current->thread.fp_regs.fpc));
+		asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
 
 #ifdef CONFIG_MATHEMU
         else if (regs->psw.mask & PSW_MASK_PSTATE) {
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index c42ffed..b0cfa6c 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -5,5 +5,6 @@
 EXTRA_AFLAGS := -traditional
 
 lib-y += delay.o string.o uaccess_std.o
+lib-$(CONFIG_32BIT) += div64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 468f4ea..027c474 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -27,9 +27,7 @@
          * yield the megahertz number of the cpu. The important function
          * is udelay and that is done using the tod clock. -- martin.
          */
-        __asm__ __volatile__(
-                "0: brct %0,0b"
-                : /* no outputs */ : "r" ((loops/2) + 1));
+	asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
 }
 
 /*
@@ -38,13 +36,12 @@
  */
 void __udelay(unsigned long usecs)
 {
-        uint64_t start_cc, end_cc;
+	uint64_t start_cc;
 
         if (usecs == 0)
                 return;
-        asm volatile ("STCK %0" : "=m" (start_cc));
+	start_cc = get_clock();
         do {
 		cpu_relax();
-                asm volatile ("STCK %0" : "=m" (end_cc));
-        } while (((end_cc - start_cc)/4096) < usecs);
+	} while (((get_clock() - start_cc)/4096) < usecs);
 }
diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c
new file mode 100644
index 0000000..0481f34
--- /dev/null
+++ b/arch/s390/lib/div64.c
@@ -0,0 +1,151 @@
+/*
+ *  arch/s390/lib/div64.c
+ *
+ *  __div64_32 implementation for 31 bit.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+#ifdef CONFIG_MARCH_G5
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 31 bit integer using signed 64/32 bit division.
+ */
+static uint32_t __div64_31(uint64_t *n, uint32_t base)
+{
+	register uint32_t reg2 asm("2");
+	register uint32_t reg3 asm("3");
+	uint32_t *words = (uint32_t *) n;
+	uint32_t tmp;
+
+	/* Special case base==1, remainder = 0, quotient = n */
+	if (base == 1)
+		return 0;
+	/*
+	 * Special case base==0 will cause a fixed point divide exception
+	 * on the dr instruction and may not happen anyway. For the
+	 * following calculation we can assume base > 1. The first
+	 * signed 64 / 32 bit division with an upper half of 0 will
+	 * give the correct upper half of the 64 bit quotient.
+	 */
+	reg2 = 0UL;
+	reg3 = words[0];
+	asm volatile(
+		"	dr	%0,%2\n"
+		: "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+	words[0] = reg3;
+	reg3 = words[1];
+	/*
+	 * To get the lower half of the 64 bit quotient and the 32 bit
+	 * remainder we have to use a little trick. Since we only have
+	 * a signed division the quotient can get too big. To avoid this
+	 * the 64 bit dividend is halved, then the signed division will
+	 * work. Afterwards the quotient and the remainder are doubled.
+	 * If the last bit of the dividend has been one the remainder
+	 * is increased by one then checked against the base. If the
+	 * remainder has overflown subtract base and increase the
+	 * quotient. Simple, no ?
+	 */
+	asm volatile(
+		"	nr	%2,%1\n"
+		"	srdl	%0,1\n"
+		"	dr	%0,%3\n"
+		"	alr	%0,%0\n"
+		"	alr	%1,%1\n"
+		"	alr	%0,%2\n"
+		"	clr	%0,%3\n"
+		"	jl	0f\n"
+		"	slr	%0,%3\n"
+		"	alr	%1,%2\n"
+		"0:\n"
+		: "+d" (reg2), "+d" (reg3), "=d" (tmp)
+		: "d" (base), "2" (1UL) : "cc" );
+	words[1] = reg3;
+	return reg2;
+}
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 32 bit integer using the unsigned 64/31 bit division.
+ */
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+	uint32_t r;
+
+	/*
+	 * If the most significant bit of base is set, divide n by
+	 * (base/2). That allows to use 64/31 bit division and gives a
+	 * good approximation of the result: n = (base/2)*q + r. The
+	 * result needs to be corrected with two simple transformations.
+	 * If base is already < 2^31-1 __div64_31 can be used directly.
+	 */
+	r = __div64_31(n, ((signed) base < 0) ? (base/2) : base);
+	if ((signed) base < 0) {
+		uint64_t q = *n;
+		/*
+		 * First transformation:
+		 * n = (base/2)*q + r
+		 *   = ((base/2)*2)*(q/2) + ((q&1) ? (base/2) : 0) + r
+		 * Since r < (base/2), r + (base/2) < base.
+		 * With q1 = (q/2) and r1 = r + ((q&1) ? (base/2) : 0)
+		 * n = ((base/2)*2)*q1 + r1 with r1 < base.
+		 */
+		if (q & 1)
+			r += base/2;
+		q >>= 1;
+		/*
+		 * Second transformation. ((base/2)*2) could have lost the
+		 * last bit.
+		 * n = ((base/2)*2)*q1 + r1
+		 *   = base*q1 - ((base&1) ? q1 : 0) + r1
+		 */
+		if (base & 1) {
+			int64_t rx = r - q;
+			/*
+			 * base is >= 2^31. The worst case for the while
+			 * loop is n=2^64-1 base=2^31+1. That gives a
+			 * maximum for q=(2^64-1)/2^31 = 0x1ffffffff. Since
+			 * base >= 2^31 the loop is finished after a maximum
+			 * of three iterations.
+			 */
+			while (rx < 0) {
+				rx += base;
+				q--;
+			}
+			r = rx;
+		}
+		*n = q;
+	}
+	return r;
+}
+
+#else /* MARCH_G5 */
+
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+	register uint32_t reg2 asm("2");
+	register uint32_t reg3 asm("3");
+	uint32_t *words = (uint32_t *) n;
+
+	reg2 = 0UL;
+	reg3 = words[0];
+	asm volatile(
+		"	dlr	%0,%2\n"
+		: "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+	words[0] = reg3;
+	reg3 = words[1];
+	asm volatile(
+		"	dlr	%0,%2\n"
+		: "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+	words[1] = reg3;
+	return reg2;
+}
+
+#endif /* MARCH_G5 */
+
+EXPORT_SYMBOL(__div64_32);
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index 86c96d6..121b293 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -35,7 +35,7 @@
 	tmp1 = -4096UL;
 	asm volatile(
 		"0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
-		"   jz    4f\n"
+		"   jz    7f\n"
 		"1:"ALR"  %0,%3\n"
 		"  "SLR"  %1,%3\n"
 		"  "SLR"  %2,%3\n"
@@ -44,13 +44,23 @@
 		"   nr    %4,%3\n"	/* %4 = (ptr + 4095) & -4096 */
 		"  "SLR"  %4,%1\n"
 		"  "CLR"  %0,%4\n"	/* copy crosses next page boundary? */
-		"   jnh   5f\n"
+		"   jnh   4f\n"
 		"3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n"
 		"  "SLR"  %0,%4\n"
-		"   j     5f\n"
-		"4:"SLR"  %0,%0\n"
-		"5: \n"
-		EX_TABLE(0b,2b) EX_TABLE(3b,5b)
+		"  "ALR"  %2,%4\n"
+		"4:"LHI"  %4,-1\n"
+		"  "ALR"  %4,%0\n"	/* copy remaining size, subtract 1 */
+		"   bras  %3,6f\n"	/* memset loop */
+		"   xc    0(1,%2),0(%2)\n"
+		"5: xc    0(256,%2),0(%2)\n"
+		"   la    %2,256(%2)\n"
+		"6:"AHI"  %4,-256\n"
+		"   jnm   5b\n"
+		"   ex    %4,0(%3)\n"
+		"   j     8f\n"
+		"7:"SLR"  %0,%0\n"
+		"8: \n"
+		EX_TABLE(0b,2b) EX_TABLE(3b,4b)
 		: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
 		: "d" (reg0) : "cc", "memory");
 	return size;
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index 9a4d4a2..f44f007 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -35,25 +35,35 @@
 	tmp1 = -256UL;
 	asm volatile(
 		"0: mvcp  0(%0,%2),0(%1),%3\n"
-		"   jz    5f\n"
+		"   jz    8f\n"
 		"1:"ALR"  %0,%3\n"
 		"   la    %1,256(%1)\n"
 		"   la    %2,256(%2)\n"
 		"2: mvcp  0(%0,%2),0(%1),%3\n"
 		"   jnz   1b\n"
-		"   j     5f\n"
+		"   j     8f\n"
 		"3: la    %4,255(%1)\n"	/* %4 = ptr + 255 */
 		"  "LHI"  %3,-4096\n"
 		"   nr    %4,%3\n"	/* %4 = (ptr + 255) & -4096 */
 		"  "SLR"  %4,%1\n"
 		"  "CLR"  %0,%4\n"	/* copy crosses next page boundary? */
-		"   jnh   6f\n"
+		"   jnh   5f\n"
 		"4: mvcp  0(%4,%2),0(%1),%3\n"
 		"  "SLR"  %0,%4\n"
-		"   j     6f\n"
-		"5:"SLR"  %0,%0\n"
-		"6: \n"
-		EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
+		"  "ALR"  %2,%4\n"
+		"5:"LHI"  %4,-1\n"
+		"  "ALR"  %4,%0\n"	/* copy remaining size, subtract 1 */
+		"   bras  %3,7f\n"	/* memset loop */
+		"   xc    0(1,%2),0(%2)\n"
+		"6: xc    0(256,%2),0(%2)\n"
+		"   la    %2,256(%2)\n"
+		"7:"AHI"  %4,-256\n"
+		"   jnm   6b\n"
+		"   ex    %4,0(%3)\n"
+		"   j     9f\n"
+		"8:"SLR"  %0,%0\n"
+		"9: \n"
+		EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
 		: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
 		: : "cc", "memory");
 	return size;
@@ -67,16 +77,22 @@
 	asm volatile(
 		"0: mvcp  0(%0,%2),0(%1),%3\n"
 		"  "SLR"  %0,%0\n"
-		"   j     3f\n"
+		"   j     5f\n"
 		"1: la    %4,255(%1)\n" /* %4 = ptr + 255 */
 		"  "LHI"  %3,-4096\n"
 		"   nr    %4,%3\n"	/* %4 = (ptr + 255) & -4096 */
 		"  "SLR"  %4,%1\n"
 		"  "CLR"  %0,%4\n"	/* copy crosses next page boundary? */
-		"   jnh   3f\n"
+		"   jnh   5f\n"
 		"2: mvcp  0(%4,%2),0(%1),%3\n"
 		"  "SLR"  %0,%4\n"
-		"3:\n"
+		"  "ALR"  %2,%4\n"
+		"3:"LHI"  %4,-1\n"
+		"  "ALR"  %4,%0\n"	/* copy remaining size, subtract 1 */
+		"   bras  %3,4f\n"
+		"   xc    0(1,%2),0(%2)\n"
+		"4: ex    %4,0(%3)\n"
+		"5:\n"
 		EX_TABLE(0b,1b) EX_TABLE(2b,3b)
 		: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
 		: : "cc", "memory");
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c
index b4957c8..6b9aec5 100644
--- a/arch/s390/math-emu/math.c
+++ b/arch/s390/math-emu/math.c
@@ -1564,52 +1564,52 @@
 }
 
 static inline void emu_load_regd(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+	if ((reg&9) != 0)	/* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* load reg from fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     ld    0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d)
-                : "1" );
+	asm volatile(		/* load reg from fp_regs.fprs[reg] */
+		"	bras	1,0f\n"
+		"	ld	0,0(%1)\n"
+		"0:	ex	%0,0(1)"
+		: /* no output */
+		: "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d)
+		: "1");
 }
 
 static inline void emu_load_rege(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+	if ((reg&9) != 0)	/* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* load reg from fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     le    0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
-                : "1" );
+	asm volatile(		/* load reg from fp_regs.fprs[reg] */
+		"	bras	1,0f\n"
+		"	le	0,0(%1)\n"
+		"0:	ex	%0,0(1)"
+		: /* no output */
+		: "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+		: "1");
 }
 
 static inline void emu_store_regd(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+	if ((reg&9) != 0)	/* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* store reg to fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     std   0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
-                : "1" );
+	asm volatile(		/* store reg to fp_regs.fprs[reg] */
+		"	bras	1,0f\n"
+		"	std	0,0(%1)\n"
+		"0:	ex	%0,0(1)"
+		: /* no output */
+		: "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
+		: "1");
 }
 
 
 static inline void emu_store_rege(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+	if ((reg&9) != 0)	/* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* store reg to fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     ste   0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
-                : "1" );
+	asm volatile(		/* store reg to fp_regs.fprs[reg] */
+		"	bras	1,0f\n"
+		"	ste	0,0(%1)\n"
+		"0:	ex	%0,0(1)"
+		: /* no output */
+		: "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+		: "1");
 }
 
 int math_emu_b3(__u8 *opcode, struct pt_regs * regs) {
@@ -2089,23 +2089,22 @@
 
         if ((opc & 0x90) == 0) {           /* test if rx in {0,2,4,6} */
                 /* we got an exception therfore ry can't be in {0,2,4,6} */
-                __asm__ __volatile (       /* load rx from fp_regs.fprs[ry] */
-                        "     bras  1,0f\n"
-                        "     ld    0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" (opc & 0xf0),
-                          "a" (&fp_regs->fprs[opc & 0xf].d)
-                        : "1" );
+		asm volatile(		/* load rx from fp_regs.fprs[ry] */
+			"	bras	1,0f\n"
+			"	ld	0,0(%1)\n"
+			"0:	ex	%0,0(1)"
+			: /* no output */
+			: "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].d)
+			: "1");
         } else if ((opc & 0x9) == 0) {     /* test if ry in {0,2,4,6} */
-                __asm__ __volatile (       /* store ry to fp_regs.fprs[rx] */
-                        "     bras  1,0f\n"
-                        "     std   0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" ((opc & 0xf) << 4),
-                          "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d)
-                        : "1" );
+		asm volatile (		/* store ry to fp_regs.fprs[rx] */
+			"	bras	1,0f\n"
+			"	std	0,0(%1)\n"
+			"0:	ex	%0,0(1)"
+			: /* no output */
+			: "a" ((opc & 0xf) << 4),
+			  "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d)
+			: "1");
         } else  /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
                 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
 	return 0;
@@ -2120,23 +2119,22 @@
 
         if ((opc & 0x90) == 0) {           /* test if rx in {0,2,4,6} */
                 /* we got an exception therfore ry can't be in {0,2,4,6} */
-                __asm__ __volatile (       /* load rx from fp_regs.fprs[ry] */
-                        "     bras  1,0f\n"
-                        "     le    0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" (opc & 0xf0),
-                          "a" (&fp_regs->fprs[opc & 0xf].f)
-                        : "1" );
+		asm volatile(		/* load rx from fp_regs.fprs[ry] */
+			"	bras	1,0f\n"
+			"	le	0,0(%1)\n"
+			"0:	ex	%0,0(1)"
+			: /* no output */
+			: "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].f)
+			: "1");
         } else if ((opc & 0x9) == 0) {     /* test if ry in {0,2,4,6} */
-                __asm__ __volatile (       /* store ry to fp_regs.fprs[rx] */
-                        "     bras  1,0f\n"
-                        "     ste   0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" ((opc & 0xf) << 4),
-                          "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f)
-                        : "1" );
+		asm volatile(		/* store ry to fp_regs.fprs[rx] */
+			"	bras	1,0f\n"
+			"	ste	0,0(%1)\n"
+			"0:	ex	%0,0(1)"
+			: /* no output */
+			: "a" ((opc & 0xf) << 4),
+			  "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f)
+			: "1");
         } else  /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
                 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
 	return 0;
diff --git a/arch/s390/math-emu/sfp-util.h b/arch/s390/math-emu/sfp-util.h
index ab556b6..5b6ca45 100644
--- a/arch/s390/math-emu/sfp-util.h
+++ b/arch/s390/math-emu/sfp-util.h
@@ -4,48 +4,51 @@
 #include <asm/byteorder.h>
 
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) ({		\
-        unsigned int __sh = (ah);			\
-        unsigned int __sl = (al);			\
-        __asm__ ("   alr  %1,%3\n"			\
-                 "   brc  12,0f\n"			\
-                 "   ahi  %0,1\n"			\
-                 "0: alr  %0,%2"			\
-                 : "+&d" (__sh), "+d" (__sl)		\
-                 : "d" (bh), "d" (bl) : "cc" );		\
-        (sh) = __sh;					\
-        (sl) = __sl;					\
+	unsigned int __sh = (ah);			\
+	unsigned int __sl = (al);			\
+	asm volatile(					\
+		"	alr	%1,%3\n"		\
+		"	brc	12,0f\n"		\
+		"	ahi	%0,1\n"			\
+		"0:	alr  %0,%2"			\
+		: "+&d" (__sh), "+d" (__sl)		\
+		: "d" (bh), "d" (bl) : "cc");		\
+	(sh) = __sh;					\
+	(sl) = __sl;					\
 })
 
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) ({		\
-       unsigned int __sh = (ah);			\
-       unsigned int __sl = (al);			\
-       __asm__ ("   slr  %1,%3\n"			\
-                "   brc  3,0f\n"			\
-                "   ahi  %0,-1\n"			\
-                "0: slr  %0,%2"				\
-                : "+&d" (__sh), "+d" (__sl)		\
-                : "d" (bh), "d" (bl) : "cc" );		\
-       (sh) = __sh;					\
-       (sl) = __sl;					\
+	unsigned int __sh = (ah);			\
+	unsigned int __sl = (al);			\
+	asm volatile(					\
+		"	slr	%1,%3\n"		\
+		"	brc	3,0f\n"			\
+		"	ahi	%0,-1\n"		\
+		"0:	slr	%0,%2"			\
+		: "+&d" (__sh), "+d" (__sl)		\
+		: "d" (bh), "d" (bl) : "cc");		\
+	(sh) = __sh;					\
+	(sl) = __sl;					\
 })
 
 /* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */
 #define umul_ppmm(wh, wl, u, v) ({			\
-        unsigned int __wh = u;				\
-        unsigned int __wl = v;				\
-        __asm__ ("   ltr  1,%0\n"			\
-                 "   mr   0,%1\n"			\
-                 "   jnm  0f\n"				\
-                 "   alr  0,%1\n"			\
-                 "0: ltr  %1,%1\n"			\
-                 "   jnm  1f\n"				\
-                 "   alr  0,%0\n"			\
-                 "1: lr   %0,0\n"			\
-                 "   lr   %1,1\n"			\
-                 : "+d" (__wh), "+d" (__wl)		\
-                 : : "0", "1", "cc" );			\
-        wh = __wh;					\
-        wl = __wl;					\
+	unsigned int __wh = u;				\
+	unsigned int __wl = v;				\
+	asm volatile(					\
+		"	ltr	1,%0\n"			\
+		"	mr	0,%1\n"			\
+		"	jnm	0f\n"				\
+		"	alr	0,%1\n"			\
+		"0:	ltr	%1,%1\n"			\
+		"	jnm	1f\n"				\
+		"	alr	0,%0\n"			\
+		"1:	lr	%0,0\n"			\
+		"	lr	%1,1\n"			\
+		: "+d" (__wh), "+d" (__wl)		\
+		: : "0", "1", "cc");			\
+	wh = __wh;					\
+	wl = __wl;					\
 })
 
 #define udiv_qrnnd(q, r, n1, n0, d)			\
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 9b11e3e..226275d 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -142,17 +142,17 @@
 
 	rx = (unsigned long) parameter;
 	ry = (unsigned long) func;
-	__asm__ __volatile__(
+	asm volatile(
 #ifdef CONFIG_64BIT
-		"   sam31\n" // switch to 31 bit
-		"   diag    %0,%1,0x64\n"
-		"   sam64\n" // switch back to 64 bit
+		"	sam31\n"
+		"	diag	%0,%1,0x64\n"
+		"	sam64\n"
 #else
-		"   diag    %0,%1,0x64\n"
+		"	diag	%0,%1,0x64\n"
 #endif
-		"   ipm     %2\n"
-		"   srl     %2,28\n"
-		: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
+		"	ipm	%2\n"
+		"	srl	%2,28\n"
+		: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
 	*ret1 = rx;
 	*ret2 = ry;
 	return rc;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 44f0cda..9c3c19f 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -353,8 +353,9 @@
 */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (tsk->pid == 1) {
+	if (is_init(tsk)) {
 		yield();
+		down_read(&mm->mmap_sem);
 		goto survive;
 	}
 	printk("VM: killing process %s\n", tsk->comm);
@@ -423,20 +424,13 @@
 
 	if (pfault_disable)
 		return -1;
-        __asm__ __volatile__(
-                "    diag  %1,%0,0x258\n"
-		"0:  j     2f\n"
-		"1:  la    %0,8\n"
+	asm volatile(
+		"	diag	%1,%0,0x258\n"
+		"0:	j	2f\n"
+		"1:	la	%0,8\n"
 		"2:\n"
-		".section __ex_table,\"a\"\n"
-		"   .align 4\n"
-#ifndef CONFIG_64BIT
-		"   .long  0b,1b\n"
-#else /* CONFIG_64BIT */
-		"   .quad  0b,1b\n"
-#endif /* CONFIG_64BIT */
-		".previous"
-                : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" );
+		EX_TABLE(0b,1b)
+		: "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc");
         __ctl_set_bit(0, 9);
         return rc;
 }
@@ -449,18 +443,11 @@
 	if (pfault_disable)
 		return;
 	__ctl_clear_bit(0,9);
-        __asm__ __volatile__(
-                "    diag  %0,0,0x258\n"
+	asm volatile(
+		"	diag	%0,0,0x258\n"
 		"0:\n"
-		".section __ex_table,\"a\"\n"
-		"   .align 4\n"
-#ifndef CONFIG_64BIT
-		"   .long  0b,0b\n"
-#else /* CONFIG_64BIT */
-		"   .quad  0b,0b\n"
-#endif /* CONFIG_64BIT */
-		".previous"
-		: : "a" (&refbk), "m" (refbk) : "cc" );
+		EX_TABLE(0b,0b)
+		: : "a" (&refbk), "m" (refbk) : "cc");
 }
 
 asmlinkage void
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index cfd9b8f..127044e 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -45,26 +45,17 @@
 {
         if (addr >= 0x7ff00000)
                 return;
+	asm volatile(
 #ifdef CONFIG_64BIT
-        asm volatile (
-		"   sam31\n"
-		"   diag %0,%0,0x10\n"
-		"0: sam64\n"
-		".section __ex_table,\"a\"\n"
-		"   .align 8\n"
-		"   .quad 0b, 0b\n"
-		".previous\n"
-		: : "a" (addr));
+		"	sam31\n"
+		"	diag	%0,%0,0x10\n"
+		"0:	sam64\n"
 #else
-        asm volatile (
-		"   diag %0,%0,0x10\n"
+		"	diag	%0,%0,0x10\n"
 		"0:\n"
-		".section __ex_table,\"a\"\n"
-		"   .align 4\n"
-		"   .long 0b, 0b\n"
-		".previous\n"
-		: : "a" (addr));
 #endif
+		EX_TABLE(0b,0b)
+		: : "a" (addr));
 }
 
 void show_mem(void)
@@ -156,11 +147,10 @@
 	S390_lowcore.kernel_asce = pgdir_k;
 
         /* enable virtual mapping in kernel mode */
-        __asm__ __volatile__("    LCTL  1,1,%0\n"
-                             "    LCTL  7,7,%0\n"
-                             "    LCTL  13,13,%0\n"
-                             "    SSM   %1" 
-			     : : "m" (pgdir_k), "m" (ssm_mask));
+	__ctl_load(pgdir_k, 1, 1);
+	__ctl_load(pgdir_k, 7, 7);
+	__ctl_load(pgdir_k, 13, 13);
+	__raw_local_irq_ssm(ssm_mask);
 
         local_flush_tlb();
         return;
@@ -241,11 +231,10 @@
 	S390_lowcore.kernel_asce = pgdir_k;
 
         /* enable virtual mapping in kernel mode */
-        __asm__ __volatile__("lctlg 1,1,%0\n\t"
-                             "lctlg 7,7,%0\n\t"
-                             "lctlg 13,13,%0\n\t"
-                             "ssm   %1"
-			     : :"m" (pgdir_k), "m" (ssm_mask));
+	__ctl_load(pgdir_k, 1, 1);
+	__ctl_load(pgdir_k, 7, 7);
+	__ctl_load(pgdir_k, 13, 13);
+	__raw_local_irq_ssm(ssm_mask);
 
         local_flush_tlb();
 
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 149d971..f664a19 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -117,7 +117,7 @@
  */
 void handle_timer_tick(struct pt_regs *regs)
 {
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index c69fd60..68663b8 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -69,7 +69,7 @@
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
 	} else {
-		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 			goto bad_area;
 	}
 
@@ -149,7 +149,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index b8162e5..3b61e06 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -298,7 +298,7 @@
 	asm ("getcon cr62, %0" : "=r" (current_ctc));
 	ctc_last_interrupt = (unsigned long) current_ctc;
 
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c
index f08d0ea..8e2f6c2 100644
--- a/arch/sh64/mm/fault.c
+++ b/arch/sh64/mm/fault.c
@@ -277,7 +277,7 @@
 			show_regs(regs);
 #endif
 		}
-		if (tsk->pid == 1) {
+		if (is_init(tsk)) {
 			panic("INIT had user mode bad_area\n");
 		}
 		tsk->thread.address = address;
@@ -319,14 +319,14 @@
  * us unable to handle the page fault gracefully.
  */
 out_of_memory:
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		panic("INIT out of memory\n");
 		yield();
 		goto survive;
 	}
 	printk("fault:Out of memory\n");
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index bfd31aa..e19b1ba 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -712,7 +712,7 @@
 {
 	write_seqlock(&xtime_lock);	/* Dummy, to show that we remember */
 	pcic_clear_clock_irq();
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 845081b0..6f84fa1 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -128,7 +128,7 @@
 #endif
 	clear_clock_irq();
 
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index b0b4fee..ca11934 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -465,7 +465,7 @@
 		profile_tick(CPU_PROFILING, regs);
 		update_process_times(user_mode(regs));
 #endif
-		do_timer(regs);
+		do_timer(1);
 
 		/* Guarantee that the following sequences execute
 		 * uninterrupted.
@@ -496,7 +496,7 @@
 {
 	write_seqlock(&xtime_lock);
 
-	do_timer(regs);
+	do_timer(1);
 
 	timer_check_rtc();
 
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 6425417..9c58132 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -11,6 +11,7 @@
 #include <linux/limits.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/tty.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/timex.h>
@@ -422,7 +423,9 @@
 			   Solaris setpgrp and setsid? */
 			ret = sys_setpgid(0, 0);
 			if (ret) return ret;
+			mutex_lock(&tty_mutex);
 			current->signal->tty = NULL;
+			mutex_unlock(&tty_mutex);
 			return process_group(current);
 		}
 	case 2: /* getsid */
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 79610b5..773a134 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -598,6 +598,11 @@
 	mconsole_reply(req, err_msg, err, 0);
 }
 
+struct mconsole_output {
+	struct list_head list;
+	struct mc_request *req;
+};
+
 static DEFINE_SPINLOCK(console_lock);
 static LIST_HEAD(clients);
 static char console_buf[MCONSOLE_MAX_DATA];
@@ -622,10 +627,10 @@
 			return;
 
 		list_for_each(ele, &clients){
-			struct mconsole_entry *entry;
+			struct mconsole_output *entry;
 
-			entry = list_entry(ele, struct mconsole_entry, list);
-			mconsole_reply_len(&entry->request, console_buf,
+			entry = list_entry(ele, struct mconsole_output, list);
+			mconsole_reply_len(entry->req, console_buf,
 					   console_index, 0, 1);
 		}
 
@@ -649,10 +654,10 @@
 static void with_console(struct mc_request *req, void (*proc)(void *),
 			 void *arg)
 {
-	struct mconsole_entry entry;
+	struct mconsole_output entry;
 	unsigned long flags;
 
-	entry.request = *req;
+	entry.req = req;
 	list_add(&entry.list, &clients);
 	spin_lock_irqsave(&console_lock, flags);
 
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 5b2f5fe..17068eb 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -131,6 +131,10 @@
 int mconsole_reply_len(struct mc_request *req, const char *str, int total,
 		       int err, int more)
 {
+	/* XXX This is a stack consumption problem.  It'd be nice to
+	 * make it global and serialize access to it, but there are a
+	 * ton of callers to this function.
+	 */
 	struct mconsole_reply reply;
 	int len, n;
 
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 664c2e2..16aa572 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -119,11 +119,6 @@
 		goto out;
 	}
 
-	if(!lp->have_mac){
- 		dev_ip_addr(dev, &lp->mac[2]);
- 		set_ether_mac(dev, lp->mac);
-	}
-
 	lp->fd = (*lp->open)(&lp->user);
 	if(lp->fd < 0){
 		err = lp->fd;
@@ -287,6 +282,37 @@
 #endif
 }
 
+static void setup_etheraddr(char *str, unsigned char *addr)
+{
+	char *end;
+	int i;
+
+	if(str == NULL)
+		goto random;
+
+	for(i=0;i<6;i++){
+		addr[i] = simple_strtoul(str, &end, 16);
+		if((end == str) ||
+		   ((*end != ':') && (*end != ',') && (*end != '\0'))){
+			printk(KERN_ERR
+			       "setup_etheraddr: failed to parse '%s' "
+			       "as an ethernet address\n", str);
+			goto random;
+		}
+		str = end + 1;
+	}
+	if(addr[0] & 1){
+		printk(KERN_ERR
+		       "Attempt to assign a broadcast ethernet address to a "
+		       "device disallowed\n");
+		goto random;
+	}
+	return;
+
+random:
+	random_ether_addr(addr)
+}
+
 static DEFINE_SPINLOCK(devices_lock);
 static LIST_HEAD(devices);
 
@@ -322,15 +348,13 @@
 	list_add(&device->list, &devices);
 	spin_unlock(&devices_lock);
 
-	if (setup_etheraddr(mac, device->mac))
-		device->have_mac = 1;
+	setup_etheraddr(mac, device->mac);
 
 	printk(KERN_INFO "Netdevice %d ", n);
-	if (device->have_mac)
-		printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
-		       device->mac[0], device->mac[1],
-		       device->mac[2], device->mac[3],
-		       device->mac[4], device->mac[5]);
+	printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
+	       device->mac[0], device->mac[1],
+	       device->mac[2], device->mac[3],
+	       device->mac[4], device->mac[5]);
 	printk(": ");
 	dev = alloc_etherdev(size);
 	if (dev == NULL) {
@@ -396,7 +420,6 @@
 		  .dev 			= dev,
 		  .fd 			= -1,
 		  .mac 			= { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
-		  .have_mac 		= device->have_mac,
 		  .protocol 		= transport->kern->protocol,
 		  .open 		= transport->user->open,
 		  .close 		= transport->user->close,
@@ -411,14 +434,12 @@
 	init_timer(&lp->tl);
 	spin_lock_init(&lp->lock);
 	lp->tl.function = uml_net_user_timer_expire;
-	if (lp->have_mac)
-		memcpy(lp->mac, device->mac, sizeof(lp->mac));
+	memcpy(lp->mac, device->mac, sizeof(lp->mac));
 
 	if (transport->user->init) 
 		(*transport->user->init)(&lp->user, dev);
 
-	if (device->have_mac)
-		set_ether_mac(dev, device->mac);
+	set_ether_mac(dev, device->mac);
 
 	return 0;
 }
@@ -747,47 +768,6 @@
 
 __uml_exitcall(close_devices);
 
-int setup_etheraddr(char *str, unsigned char *addr)
-{
-	char *end;
-	int i;
-
-	if(str == NULL)
-		return(0);
-	for(i=0;i<6;i++){
-		addr[i] = simple_strtoul(str, &end, 16);
-		if((end == str) ||
-		   ((*end != ':') && (*end != ',') && (*end != '\0'))){
-			printk(KERN_ERR 
-			       "setup_etheraddr: failed to parse '%s' "
-			       "as an ethernet address\n", str);
-			return(0);
-		}
-		str = end + 1;
-	}
-	if(addr[0] & 1){
-		printk(KERN_ERR 
-		       "Attempt to assign a broadcast ethernet address to a "
-		       "device disallowed\n");
-		return(0);
-	}
-	return(1);
-}
-
-void dev_ip_addr(void *d, unsigned char *bin_buf)
-{
-	struct net_device *dev = d;
-	struct in_device *ip = dev->ip_ptr;
-	struct in_ifaddr *in;
-
-	if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
-		printk(KERN_WARNING "dev_ip_addr - device not assigned an "
-		       "IP address\n");
-		return;
-	}
-	memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
-}
-
 struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
 {
 	if((skb != NULL) && (skb_tailroom(skb) < extra)){
@@ -825,7 +805,7 @@
 	struct net_device *dev = d;
 	struct in_device *ip = dev->ip_ptr;
 	struct in_ifaddr *in;
-	__u32 *mask_out = m;
+	__be32 *mask_out = m;
 
 	if(ip == NULL) 
 		return(1);
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 107c5e4..f3a3f8a 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -12,6 +12,7 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
+#include <sys/time.h>
 #include "user.h"
 #include "user_util.h"
 #include "kern_util.h"
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c
index 3683ed4..9016c68 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -8,6 +8,7 @@
 #include "chan_user.h"
 #include "os.h"
 
+/* This address is used only as a unique identifer */
 static int null_chan;
 
 static void *null_init(char *str, int device, const struct chan_opts *opts)
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index ae99094..73b2bdd 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -20,6 +20,10 @@
 
 #define RNG_MISCDEV_MINOR		183 /* official */
 
+/* Changed at init time, in the non-modular case, and at module load
+ * time, in the module case.  Presumably, the module subsystem
+ * protects against a module being loaded twice at the same time.
+ */
 static int random_fd = -1;
 
 static int rng_dev_open (struct inode *inode, struct file *filp)
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 6d2cf32..9115392 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -9,6 +9,8 @@
 /*
  * Don't register by default -- as this registeres very early in the
  * boot process it becomes the default console.
+ *
+ * Initialized at init time.
  */
 static int use_stderr_console = 0;
 
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 5e44adb..e4bfcfe 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -108,6 +108,7 @@
 	return line_open(vts, tty);
 }
 
+/* Set in an initcall, checked in an exitcall */
 static int con_init_done = 0;
 
 static const struct tty_operations console_ops = {
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 3408531..5fa4c8e 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -668,18 +668,15 @@
 	if(dev->file == NULL)
 		goto out;
 
-	if (ubd_open_dev(dev))
-		goto out;
-
 	err = ubd_file_size(dev, &dev->size);
 	if(err < 0)
-		goto out_close;
+		goto out;
 
 	dev->size = ROUND_BLOCK(dev->size);
 
 	err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
 	if(err)
-		goto out_close;
+		goto out;
 
 	if(fake_major != MAJOR_NR)
 		ubd_new_disk(fake_major, dev->size, n,
@@ -691,8 +688,6 @@
 		make_ide_entries(ubd_gendisk[n]->disk_name);
 
 	err = 0;
-out_close:
-	ubd_close(dev);
 out:
 	return err;
 }
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 769fba4..280459f 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -18,7 +18,6 @@
 	struct platform_device pdev;
 	int index;
 	unsigned char mac[ETH_ALEN];
-	int have_mac;
 };
 
 struct uml_net_private {
@@ -29,7 +28,6 @@
 	struct net_device_stats stats;
 	int fd;
 	unsigned char mac[ETH_ALEN];
-	int have_mac;
 	unsigned short (*protocol)(struct sk_buff *);
 	int (*open)(void *);
 	void (*close)(int, void *);
@@ -62,7 +60,6 @@
 
 extern struct net_device *ether_init(int);
 extern unsigned short ether_protocol(struct sk_buff *);
-extern int setup_etheraddr(char *str, unsigned char *addr);
 extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
 extern int tap_setup_common(char *str, char *type, char **dev_name, 
 			    char **mac_out, char **gate_addr);
@@ -70,14 +67,3 @@
 extern unsigned short eth_protocol(struct sk_buff *skb);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 47ef7cb..19f207c 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -25,9 +25,8 @@
 };
 
 extern void ether_user_init(void *data, void *dev);
-extern void dev_ip_addr(void *d, unsigned char *bin_buf);
-extern void iter_addresses(void *d, void (*cb)(unsigned char *, 
-					       unsigned char *, void *), 
+extern void iter_addresses(void *d, void (*cb)(unsigned char *,
+					       unsigned char *, void *),
 			   void *arg);
 
 extern void *get_output_buffer(int *len_out);
@@ -52,14 +51,3 @@
 extern int dev_netmask(void *d, void *m);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index d21ebad..8b7f2cd 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -16,9 +16,13 @@
 static int read_proc_exitcode(char *page, char **start, off_t off,
 			      int count, int *eof, void *data)
 {
-	int len;
+	int len, val;
 
-	len = sprintf(page, "%d\n", uml_exitcode);
+	/* Save uml_exitcode in a local so that we don't need to guarantee
+	 * that sprintf accesses it atomically.
+	 */
+	val = uml_exitcode;
+	len = sprintf(page, "%d\n", val);
 	len -= off;
 	if(len <= off+count) *eof = 1;
 	*start = page + off;
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 79c2270..4cd2ff5 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -61,8 +61,10 @@
 #endif
 
 	*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
-	*pte = pte_mkexec(*pte);
-	*pte = pte_wrprotect(*pte);
+	/* 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);
 	return(0);
 
  out_pmd:
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
deleted file mode 100644
index 0f3d5d0..0000000
--- a/arch/um/kernel/skas/process_kern.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/config.h"
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/interrupt.h"
-#include "linux/string.h"
-#include "linux/mm.h"
-#include "linux/slab.h"
-#include "linux/utsname.h"
-#include "linux/fs.h"
-#include "linux/utime.h"
-#include "linux/smp_lock.h"
-#include "linux/module.h"
-#include "linux/init.h"
-#include "linux/capability.h"
-#include "linux/vmalloc.h"
-#include "linux/spinlock.h"
-#include "linux/proc_fs.h"
-#include "linux/ptrace.h"
-#include "linux/random.h"
-#include "linux/personality.h"
-#include "asm/unistd.h"
-#include "asm/mman.h"
-#include "asm/segment.h"
-#include "asm/stat.h"
-#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/tlbflush.h"
-#include "asm/uaccess.h"
-#include "asm/user.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "signal_kern.h"
-#include "init.h"
-#include "irq_user.h"
-#include "mem_user.h"
-#include "tlb.h"
-#include "frame_kern.h"
-#include "sigcontext.h"
-#include "os.h"
-#include "mode.h"
-#include "mode_kern.h"
-#include "choose-mode.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
- * entry.
- */
-struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-
-int external_pid(void *t)
-{
-	struct task_struct *task = t ? t : current;
-
-	return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
-}
-
-int pid_to_processor_id(int pid)
-{
-	int i;
-
-	for(i = 0; i < ncpus; i++){
-		if(cpu_tasks[i].pid == pid) return(i);
-	}
-	return(-1);
-}
-
-void free_stack(unsigned long stack, int order)
-{
-	free_pages(stack, order);
-}
-
-unsigned long alloc_stack(int order, int atomic)
-{
-	unsigned long page;
-	gfp_t flags = GFP_KERNEL;
-
-	if (atomic)
-		flags = GFP_ATOMIC;
-	page = __get_free_pages(flags, order);
-	if(page == 0)
-		return(0);
-	stack_protections(page);
-	return(page);
-}
-
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	int pid;
-
-	current->thread.request.u.thread.proc = fn;
-	current->thread.request.u.thread.arg = arg;
-	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
-		      &current->thread.regs, 0, NULL, NULL);
-	if(pid < 0)
-		panic("do_fork failed in kernel_thread, errno = %d", pid);
-	return(pid);
-}
-
-void set_current(void *t)
-{
-	struct task_struct *task = t;
-
-	cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
-		{ external_pid(task), task });
-}
-
-void *_switch_to(void *prev, void *next, void *last)
-{
-        struct task_struct *from = prev;
-        struct task_struct *to= next;
-
-        to->thread.prev_sched = from;
-        set_current(to);
-
-	do {
-		current->thread.saved_task = NULL ;
-		CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
-		if(current->thread.saved_task)
-			show_regs(&(current->thread.regs));
-		next= current->thread.saved_task;
-		prev= current;
-	} while(current->thread.saved_task);
-
-        return(current->thread.prev_sched);
-
-}
-
-void interrupt_end(void)
-{
-	if(need_resched()) schedule();
-	if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
-}
-
-void release_thread(struct task_struct *task)
-{
-	CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
-}
-
-void exit_thread(void)
-{
-	unprotect_stack((unsigned long) current_thread);
-}
-
-void *get_current(void)
-{
-	return(current);
-}
-
-int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
-		unsigned long stack_top, struct task_struct * p,
-		struct pt_regs *regs)
-{
-	int ret;
-
-	p->thread = (struct thread_struct) INIT_THREAD;
-	ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
-				clone_flags, sp, stack_top, p, regs);
-
-	if (ret || !current->thread.forking)
-		goto out;
-
-	clear_flushed_tls(p);
-
-	/*
-	 * Set a new TLS for the child thread?
-	 */
-	if (clone_flags & CLONE_SETTLS)
-		ret = arch_copy_tls(p);
-
-out:
-	return ret;
-}
-
-void initial_thread_cb(void (*proc)(void *), void *arg)
-{
-	int save_kmalloc_ok = kmalloc_ok;
-
-	kmalloc_ok = 0;
-	CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
-			 arg);
-	kmalloc_ok = save_kmalloc_ok;
-}
-
-unsigned long stack_sp(unsigned long page)
-{
-	return(page + PAGE_SIZE - sizeof(void *));
-}
-
-int current_pid(void)
-{
-	return(current->pid);
-}
-
-void default_idle(void)
-{
-	CHOOSE_MODE(uml_idle_timer(), (void) 0);
-
-	while(1){
-		/* endless idle loop with no priority at all */
-
-		/*
-		 * although we are an idle CPU, we do not want to
-		 * get into the scheduler unnecessarily.
-		 */
-		if(need_resched())
-			schedule();
-
-		idle_sleep(10);
-	}
-}
-
-void cpu_idle(void)
-{
-	CHOOSE_MODE(init_idle_tt(), init_idle_skas());
-}
-
-int page_size(void)
-{
-	return(PAGE_SIZE);
-}
-
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
-		      pte_t *pte_out)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	pte_t ptent;
-
-	if(task->mm == NULL)
-		return(ERR_PTR(-EINVAL));
-	pgd = pgd_offset(task->mm, addr);
-	if(!pgd_present(*pgd))
-		return(ERR_PTR(-EINVAL));
-
-	pud = pud_offset(pgd, addr);
-	if(!pud_present(*pud))
-		return(ERR_PTR(-EINVAL));
-
-	pmd = pmd_offset(pud, addr);
-	if(!pmd_present(*pmd))
-		return(ERR_PTR(-EINVAL));
-
-	pte = pte_offset_kernel(pmd, addr);
-	ptent = *pte;
-	if(!pte_present(ptent))
-		return(ERR_PTR(-EINVAL));
-
-	if(pte_out != NULL)
-		*pte_out = ptent;
-	return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
-}
-
-char *current_cmd(void)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
-	return("(Unknown)");
-#else
-	void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
-	return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-#endif
-}
-
-void force_sigbus(void)
-{
-	printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
-	       current->pid);
-	lock_kernel();
-	sigaddset(&current->pending.signal, SIGBUS);
-	recalc_sigpending();
-	current->flags |= PF_SIGNALED;
-	do_exit(SIGBUS | 0x80);
-}
-
-void dump_thread(struct pt_regs *regs, struct user *u)
-{
-}
-
-void enable_hlt(void)
-{
-	panic("enable_hlt");
-}
-
-EXPORT_SYMBOL(enable_hlt);
-
-void disable_hlt(void)
-{
-	panic("disable_hlt");
-}
-
-EXPORT_SYMBOL(disable_hlt);
-
-void *um_kmalloc(int size)
-{
-	return kmalloc(size, GFP_KERNEL);
-}
-
-void *um_kmalloc_atomic(int size)
-{
-	return kmalloc(size, GFP_ATOMIC);
-}
-
-void *um_vmalloc(int size)
-{
-	return vmalloc(size);
-}
-
-void *um_vmalloc_atomic(int size)
-{
-	return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
-}
-
-int __cant_sleep(void) {
-	return in_atomic() || irqs_disabled() || in_interrupt();
-	/* Is in_interrupt() really needed? */
-}
-
-unsigned long get_fault_addr(void)
-{
-	return((unsigned long) current->thread.fault_addr);
-}
-
-EXPORT_SYMBOL(get_fault_addr);
-
-void not_implemented(void)
-{
-	printk(KERN_DEBUG "Something isn't implemented in here\n");
-}
-
-EXPORT_SYMBOL(not_implemented);
-
-int user_context(unsigned long sp)
-{
-	unsigned long stack;
-
-	stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
-	return(stack != (unsigned long) current_thread);
-}
-
-extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
-
-void do_uml_exitcalls(void)
-{
-	exitcall_t *call;
-
-	call = &__uml_exitcall_end;
-	while (--call >= &__uml_exitcall_begin)
-		(*call)();
-}
-
-char *uml_strdup(char *string)
-{
-	return kstrdup(string, GFP_KERNEL);
-}
-
-int copy_to_user_proc(void __user *to, void *from, int size)
-{
-	return(copy_to_user(to, from, size));
-}
-
-int copy_from_user_proc(void *to, void __user *from, int size)
-{
-	return(copy_from_user(to, from, size));
-}
-
-int clear_user_proc(void __user *buf, int size)
-{
-	return(clear_user(buf, size));
-}
-
-int strlen_user_proc(char __user *str)
-{
-	return(strlen_user(str));
-}
-
-int smp_sigio_handler(void)
-{
-#ifdef CONFIG_SMP
-	int cpu = current_thread->cpu;
-	IPI_handler(cpu);
-	if(cpu != 0)
-		return(1);
-#endif
-	return(0);
-}
-
-int cpu(void)
-{
-	return(current_thread->cpu);
-}
-
-static atomic_t using_sysemu = ATOMIC_INIT(0);
-int sysemu_supported;
-
-void set_using_sysemu(int value)
-{
-	if (value > sysemu_supported)
-		return;
-	atomic_set(&using_sysemu, value);
-}
-
-int get_using_sysemu(void)
-{
-	return atomic_read(&using_sysemu);
-}
-
-static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
-{
-	if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
-		*eof = 1;
-
-	return strlen(buf);
-}
-
-static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
-{
-	char tmp[2];
-
-	if (copy_from_user(tmp, buf, 1))
-		return -EFAULT;
-
-	if (tmp[0] >= '0' && tmp[0] <= '2')
-		set_using_sysemu(tmp[0] - '0');
-	return count; /*We use the first char, but pretend to write everything*/
-}
-
-int __init make_proc_sysemu(void)
-{
-	struct proc_dir_entry *ent;
-	if (!sysemu_supported)
-		return 0;
-
-	ent = create_proc_entry("sysemu", 0600, &proc_root);
-
-	if (ent == NULL)
-	{
-		printk(KERN_WARNING "Failed to register /proc/sysemu\n");
-		return(0);
-	}
-
-	ent->read_proc  = proc_read_sysemu;
-	ent->write_proc = proc_write_sysemu;
-
-	return 0;
-}
-
-late_initcall(make_proc_sysemu);
-
-int singlestepping(void * t)
-{
-	struct task_struct *task = t ? t : current;
-
-	if ( ! (task->ptrace & PT_DTRACE) )
-		return(0);
-
-	if (task->thread.singlestep_syscall)
-		return(1);
-
-	return 2;
-}
-
-/*
- * Only x86 and x86_64 have an arch_align_stack().
- * All other arches have "#define arch_align_stack(x) (x)"
- * in their asm/system.h
- * As this is included in UML from asm-um/system-generic.h,
- * we can use it to behave as the subarch does.
- */
-#ifndef arch_align_stack
-unsigned long arch_align_stack(unsigned long sp)
-{
-	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
-	return sp & ~0xf;
-}
-#endif
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 820affb..a92965f 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -93,7 +93,7 @@
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 
-	do_timer(regs);
+	do_timer(1);
 
 	nsecs = get_time();
 	xtime.tv_sec = nsecs / NSEC_PER_SEC;
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 61a23ff..c7b195c 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -120,7 +120,7 @@
  * us unable to handle the page fault gracefully.
  */
 out_of_memory:
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		up_read(&mm->mmap_sem);
 		yield();
 		down_read(&mm->mmap_sem);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index b170b47..4203681 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -132,6 +132,9 @@
 	else if(found < 0)
 		printf("read returned errno %d\n", -found);
 
+out:
+	close(fd);
+
 	return;
 
 found:
@@ -141,11 +144,12 @@
 
 	if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
 		printf("not tmpfs\n");
-		return;
+		goto out;
 	}
 
 	printf("OK\n");
 	default_tmpdir = "/dev/shm";
+	goto out;
 }
 
 /*
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
index a0b4669..f4d1a4d 100644
--- a/arch/v850/kernel/time.c
+++ b/arch/v850/kernel/time.c
@@ -51,7 +51,7 @@
 	if (mach_tick)
 	  mach_tick ();
 
-	do_timer (regs);
+	do_timer (1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
index 6a55f87..697f0aa 100644
--- a/arch/x86_64/kernel/pci-swiotlb.c
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -3,7 +3,8 @@
 #include <linux/pci.h>
 #include <linux/cache.h>
 #include <linux/module.h>
-#include <asm/dma-mapping.h>
+#include <linux/dma-mapping.h>
+
 #include <asm/proto.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 1c255ee..7ea3bf2 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -415,16 +415,16 @@
 				(((long) offset << US_SCALE) / vxtime.tsc_quot) - 1;
 	}
 
-	if (lost > 0) {
+	if (lost > 0)
 		handle_lost_ticks(lost, regs);
-		jiffies += lost;
-	}
+	else
+		lost = 0;
 
 /*
  * Do the timer stuff.
  */
 
-	do_timer(regs);
+	do_timer(lost + 1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 1a17b07..3751b47 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -244,7 +244,7 @@
 
 int unhandled_signal(struct task_struct *tsk, int sig)
 {
-	if (tsk->pid == 1)
+	if (is_init(tsk))
 		return 1;
 	if (tsk->ptrace & PT_PTRACED)
 		return 0;
@@ -464,7 +464,7 @@
 		case PF_PROT:		/* read, present */
 			goto bad_area;
 		case 0:			/* read, not present */
-			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 				goto bad_area;
 	}
 
@@ -580,7 +580,7 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) { 
+	if (is_init(current)) {
 		yield();
 		goto again;
 	}
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 412ab32..241db20 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -175,7 +175,7 @@
 
 		last_ccount_stamp = next;
 		next += CCOUNT_PER_JIFFY;
-		do_timer (regs); /* Linux handler in kernel/timer.c */
+		do_timer (1); /* Linux handler in kernel/timer.c */
 
 		if (ntp_synced() &&
 		    xtime.tv_sec - last_rtc_update >= 659 &&
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index a945a33..dd0dbec 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -144,7 +144,7 @@
 	 */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	if (current->pid == 1) {
+	if (is_init(current)) {
 		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
index d96164e..15d6441 100644
--- a/arch/xtensa/platform-iss/network.c
+++ b/arch/xtensa/platform-iss/network.c
@@ -201,7 +201,7 @@
 	struct net_device *dev = d;
 	struct in_device *ip = dev->ip_ptr;
 	struct in_ifaddr *in;
-	u32 addr;
+	__be32 addr;
 
 	if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
 		printk(KERN_WARNING "Device not assigned an IP address!\n");
diff --git a/block/blktrace.c b/block/blktrace.c
index 2b4ef2b..8ff3344 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -450,8 +450,10 @@
  **/
 void blk_trace_shutdown(request_queue_t *q)
 {
-	blk_trace_startstop(q, 0);
-	blk_trace_remove(q);
+	if (q->blk_trace) {
+		blk_trace_startstop(q, 0);
+		blk_trace_remove(q);
+	}
 }
 
 /*
diff --git a/block/genhd.c b/block/genhd.c
index 25d1f42..653919d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -295,10 +295,15 @@
 
 static int __init genhd_device_init(void)
 {
+	int err;
+
 	bdev_map = kobj_map_init(base_probe, &block_subsys_lock);
 	blk_dev_init();
-	subsystem_register(&block_subsys);
-	return 0;
+	err = subsystem_register(&block_subsys);
+	if (err < 0)
+		printk(KERN_WARNING "%s: subsystem_register error: %d\n",
+			__FUNCTION__, err);
+	return err;
 }
 
 subsys_initcall(genhd_device_init);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 9c3a06b..51dc0ed 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1847,8 +1847,7 @@
 	if (q->queue_tags)
 		__blk_queue_free_tags(q);
 
-	if (q->blk_trace)
-		blk_trace_shutdown(q);
+	blk_trace_shutdown(q);
 
 	kmem_cache_free(requestq_cachep, q);
 }
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 99837d9..3f4aa0c 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -311,7 +311,7 @@
 
 config PATA_LEGACY
 	tristate "Legacy ISA PATA support (Experimental)"
-	depends on PCI && EXPERIMENTAL
+	depends on ISA && EXPERIMENTAL
 	help
 	  This option enables support for ISA/VLB bus legacy PATA
 	  ports and allows them to be accessed via the new ATA layer.
@@ -400,6 +400,7 @@
 
 config PATA_QDI
 	tristate "QDI VLB PATA support"
+	depends on ISA
 	help
 	  Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
 
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 1d1c30a..377425e 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -143,7 +143,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.irq_handler	= ata_interrupt,
 	.irq_clear	= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index ffa111e..5719704 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -643,11 +643,9 @@
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
-		ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
-		ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
+		return -ENOENT;
+		
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 753b015..b4abd68 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5453,6 +5453,11 @@
 	int rc;
 
 	DPRINTK("ENTER\n");
+	
+	if (ent->irq == 0) {
+		dev_printk(KERN_ERR, dev, "is not available: No interrupt assigned.\n");
+		return 0;
+	}
 	/* alloc a container for our list of ATA ports (buses) */
 	host = kzalloc(sizeof(struct ata_host) +
 		       (ent->n_ports * sizeof(void *)), GFP_KERNEL);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 3fa80f0..02b2b27 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1515,7 +1515,11 @@
 	if (prereset) {
 		rc = prereset(ap);
 		if (rc) {
-			ata_port_printk(ap, KERN_ERR,
+			if (rc == -ENOENT) {
+				ata_port_printk(ap, KERN_DEBUG, "port disabled. ignoring.\n");
+				ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
+			} else
+				ata_port_printk(ap, KERN_ERR,
 					"prereset failed (errno=%d)\n", rc);
 			return rc;
 		}
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 688bb55..08b3a40 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -881,7 +881,7 @@
 	probe_ent->private_data = port[0]->private_data;
 
 	if (port_mask & ATA_PORT_PRIMARY) {
-		probe_ent->irq = 14;
+		probe_ent->irq = ATA_PRIMARY_IRQ;
 		probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
 		probe_ent->port[0].altstatus_addr =
 		probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
@@ -896,9 +896,9 @@
 
 	if (port_mask & ATA_PORT_SECONDARY) {
 		if (probe_ent->irq)
-			probe_ent->irq2 = 15;
+			probe_ent->irq2 = ATA_SECONDARY_IRQ;
 		else
-			probe_ent->irq = 15;
+			probe_ent->irq = ATA_SECONDARY_IRQ;
 		probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
 		probe_ent->port[1].altstatus_addr =
 		probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 8448ee6..87af3b5 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -369,7 +369,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -410,7 +410,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -448,7 +448,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -485,7 +485,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 3293cf9..599ee26 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.2.3"
+#define DRV_VERSION "0.2.4"
 
 /**
  *	timing_setup		-	shared timing computation and load
@@ -137,11 +137,8 @@
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u8 ata66;
 
-	if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
+		return -ENOENT;
 
 	pci_read_config_byte(pdev, 0x42, &ata66);
 	if (ata66 & bitmask[ap->port_no])
@@ -167,11 +164,9 @@
 		{ 0x40, 1, 0x01, 0x01 }
 	};
 
-	if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
+		return -ENOENT;
+
 	/* No host side cable detection */
 	ap->cbl = ATA_CBL_PATA80;
 	return ata_std_prereset(ap);
@@ -262,12 +257,8 @@
 	u8 ata66;
 	u16 udma;
 
-	if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
-
+	if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
+		return -ENOENT;
 
 	pci_read_config_byte(pdev, 0x52, &ata66);
 	if (ata66 & bitmask[ap->port_no])
@@ -368,7 +359,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -402,7 +393,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -436,7 +427,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -470,7 +461,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -504,7 +495,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -538,7 +529,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index d6ef3bf..c4ccb75 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -28,7 +28,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_artop"
-#define DRV_VERSION	"0.4.1"
+#define DRV_VERSION	"0.4.2"
 
 /*
  *	The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -47,11 +47,9 @@
 		{ 0x4AU, 1U, 0x04UL, 0x04UL },	/* port 1 */
 	};
 
-	if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+		return -ENOENT;
+
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
@@ -90,11 +88,9 @@
 	u8 tmp;
 
 	/* Odd numbered device ids are the units with enable bits (the -R cards) */
-	if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+		return -ENOENT;
+
 	pci_read_config_byte(pdev, 0x49, &tmp);
 	if (tmp & (1 >> ap->port_no))
 		ap->cbl = ATA_CBL_PATA40;
@@ -344,7 +340,7 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.eng_timeout		= ata_eng_timeout,
+
 	.data_xfer		= ata_pio_data_xfer,
 
 	.irq_handler		= ata_interrupt,
@@ -379,8 +375,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 3f78a1e..6c2269b 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -22,7 +22,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_atiixp"
-#define DRV_VERSION "0.4.2"
+#define DRV_VERSION "0.4.3"
 
 enum {
 	ATIIXP_IDE_PIO_TIMING	= 0x40,
@@ -41,11 +41,9 @@
 		{ 0x48, 1, 0x08, 0x00 }
 	};
 
-	if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
+		return -ENOENT;
+
 	ap->cbl = ATA_CBL_PATA80;
 	return ata_std_prereset(ap);
 }
@@ -244,7 +242,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index abf1bb7..e92b0ef 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -301,7 +301,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -335,7 +335,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -369,7 +369,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 792ce48..a6c6ceb 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -193,8 +193,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index f3d8a3b..7bba4d95 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -207,7 +207,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= cs5530_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index 69d6b42..d64fcdc 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -211,7 +211,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index fd55474e..dfa5ac5 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -162,7 +162,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index c30bc18..95cd1ca 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -22,7 +22,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_efar"
-#define DRV_VERSION	"0.4.1"
+#define DRV_VERSION	"0.4.2"
 
 /**
  *	efar_pre_reset	-	check for 40/80 pin
@@ -42,11 +42,9 @@
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u8 tmp;
 
-	if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
+		return -ENOENT;
+
 	pci_read_config_byte(pdev, 0x47, &tmp);
 	if (tmp & (2 >> ap->port_no))
 		ap->cbl = ATA_CBL_PATA40;
@@ -263,8 +261,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 94bb1df..cf656ec 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -360,7 +360,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 532a792..10318c0 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -793,7 +793,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -832,7 +832,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -872,7 +872,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -912,7 +912,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 06c8db0..5c5d4f6 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -372,7 +372,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= hpt3x2n_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 1527701..1f084ab 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -145,7 +145,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 73948c8..640b8b0 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -52,7 +52,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index af39097..82a46ff 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -703,7 +703,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= it821x_smart_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -739,7 +739,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= it821x_passthru_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_clear	= ata_bmdma_irq_clear,
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 6832a64..be3a866 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -51,7 +51,7 @@
 	/* Check if our port is enabled */
 	pci_read_config_dword(pdev, 0x40, &control);
 	if ((control & port_mask) == 0)
-		return 0;
+		return -ENOENT;
 
 	/* There are two basic mappings. One has the two SATA ports merged
 	   as master/slave and the secondary as PATA, the other has only the
@@ -164,8 +164,7 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	/* Timeout handling. Special recovery hooks here */
-	.eng_timeout		= ata_eng_timeout,
+	/* IRQ-related hooks */
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index ad37c22..10231ef 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -161,7 +161,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
@@ -186,7 +186,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
@@ -296,7 +296,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= pdc_data_xfer_vlb,
 
 	.irq_handler	= ata_interrupt,
@@ -348,7 +348,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,	/* Check vlb/noirq */
 
 	.irq_handler	= ata_interrupt,
@@ -411,7 +411,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,	/* FIXME: Check 32bit and noirq */
 
 	.irq_handler	= ata_interrupt,
@@ -529,7 +529,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -659,7 +659,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= opti82c46x_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 1958c4e..3c65393 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -18,7 +18,7 @@
  * The driver conciously keeps this logic internally to avoid pushing quirky
  * PATA history into the clean libata layer.
  *
- * Thinkpad specific note: If you boot an MPIIX using thinkpad with a PCMCIA
+ * Thinkpad specific note: If you boot an MPIIX using a thinkpad with a PCMCIA
  * hard disk present this driver will not detect it. This is not a bug. In this
  * configuration the secondary port of the MPIIX is disabled and the addresses
  * are decoded by the PCMCIA bridge and therefore are for a generic IDE driver
@@ -35,7 +35,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_mpiix"
-#define DRV_VERSION "0.7.1"
+#define DRV_VERSION "0.7.2"
 
 enum {
 	IDETIM = 0x6C,		/* IDE control register */
@@ -54,11 +54,8 @@
 		{ 0x6F, 1, 0x80, 0x80 }
 	};
 
-	if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no]))
+		return -ENOENT;
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 16cb254..76eb9c9 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -90,8 +90,7 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	/* Timeout handling. Special recovery hooks here */
-	.eng_timeout		= ata_eng_timeout,
+	/* IRQ-related hooks */
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 93d6646..2005a95 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -45,11 +45,8 @@
 		{ 0x47, 1, 0x08, 0x08 }
 	};
 
-	if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
+		return -ENOENT;
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
@@ -179,7 +176,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ns87410_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 04c618a..31a285c 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -25,7 +25,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_oldpiix"
-#define DRV_VERSION	"0.5.1"
+#define DRV_VERSION	"0.5.2"
 
 /**
  *	oldpiix_pre_reset		-	probe begin
@@ -42,11 +42,8 @@
 		{ 0x43U, 1U, 0x80UL, 0x80UL },	/* port 1 */
 	};
 
-	if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
+		return -ENOENT;
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index c3d0132..57fe21f 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -34,7 +34,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_opti"
-#define DRV_VERSION "0.2.4"
+#define DRV_VERSION "0.2.5"
 
 enum {
 	READ_REG	= 0,	/* index of Read cycle timing register */
@@ -59,11 +59,9 @@
 		{ 0x40, 1, 0x08, 0x00 }
 	};
 
-	if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
+		return -ENOENT;
+
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
@@ -229,7 +227,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 177a455..7296a20 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -33,7 +33,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_optidma"
-#define DRV_VERSION "0.2.1"
+#define DRV_VERSION "0.2.2"
 
 enum {
 	READ_REG	= 0,	/* index of Read cycle timing register */
@@ -59,11 +59,9 @@
 		0x40, 1, 0x08, 0x00
 	};
 
-	if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits)) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
+		return -ENOENT;
+
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
@@ -388,7 +386,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -423,7 +421,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 62b25cd..cb501e1 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -87,7 +87,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 31ab9c8..bd4ed67 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -36,7 +36,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"pata_pdc2027x"
-#define DRV_VERSION	"0.74-ac3"
+#define DRV_VERSION	"0.74-ac5"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -311,10 +311,8 @@
 static int pdc2027x_prereset(struct ata_port *ap)
 {
 	/* Check whether port enabled */
-	if (!pdc2027x_port_enabled(ap)) {
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pdc2027x_port_enabled(ap))
+		return -ENOENT;
 	pdc2027x_cbl_detect(ap);
 	return ata_std_prereset(ap);
 }
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 35cfdf0a..7977f47 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -184,7 +184,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= qdi_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= qdi_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -212,7 +212,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= qdi_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= qdi_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 277f841..c20bcf4 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -255,8 +255,6 @@
 	.qc_issue		= radisys_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 3c6d84f..eccc6fd 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -112,7 +112,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.freeze		= ata_bmdma_freeze,
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 4166c1a..107e6cd 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -217,7 +217,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= sc1200_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index af45611..a5c8d7e 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_serverworks"
-#define DRV_VERSION "0.3.6"
+#define DRV_VERSION "0.3.7"
 
 #define SVWKS_CSB5_REVISION_NEW	0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
 #define SVWKS_CSB6_REVISION	0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
@@ -128,7 +128,7 @@
 	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable },
 	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable },
 	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN,  sun_cable },
-	{ PCI_DEVICE_ID_SERVERWORKS_OSB4, PCI_ANY_ID, osb4_cable },
+	{ PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable },
 	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable },
 	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable },
 	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable },
@@ -352,10 +352,12 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
+	.irq_clear	= ata_bmdma_irq_clear,
+
 	.port_start	= ata_port_start,
 	.port_stop	= ata_port_stop,
 	.host_stop	= ata_host_stop
@@ -385,10 +387,12 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
+	.irq_clear	= ata_bmdma_irq_clear,
+
 	.port_start	= ata_port_start,
 	.port_stop	= ata_port_stop,
 	.host_stop	= ata_host_stop
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 8f7db96..c8b2e26 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -251,7 +251,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 2e555168..17791e2 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -34,7 +34,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME	"pata_sis"
-#define DRV_VERSION	"0.4.3"
+#define DRV_VERSION	"0.4.4"
 
 struct sis_chipset {
 	u16 device;			/* PCI host ID */
@@ -74,11 +74,9 @@
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u16 tmp;
 
-	if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
+		return -ENOENT;
+
 	/* The top bit of this register is the cable detect bit */
 	pci_read_config_word(pdev, 0x50 + 2 * ap->port_no, &tmp);
 	if (tmp & 0x8000)
@@ -575,8 +573,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
@@ -610,8 +606,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
@@ -646,8 +640,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
@@ -681,8 +673,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
@@ -716,8 +706,6 @@
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
-
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index f849978..5b762ac 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -19,7 +19,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_sl82c105"
-#define DRV_VERSION "0.2.2"
+#define DRV_VERSION "0.2.3"
 
 enum {
 	/*
@@ -49,11 +49,8 @@
 	};
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-	if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		dev_printk(KERN_INFO, &pdev->dev, "port disabled. ignoring.\n");
-		return 0;
-	}
+	if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
+		return -ENOENT;
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
@@ -264,7 +261,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index 36f7887..a954ed9 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -46,13 +46,13 @@
 #define DRV_VERSION "0.2.5"
 
 /**
- *	triflex_probe_init		-	probe begin
+ *	triflex_prereset		-	probe begin
  *	@ap: ATA port
  *
  *	Set up cable type and use generic probe init
  */
 
-static int triflex_probe_init(struct ata_port *ap)
+static int triflex_prereset(struct ata_port *ap)
 {
 	static const struct pci_bits triflex_enable_bits[] = {
 		{ 0x80, 1, 0x01, 0x01 },
@@ -61,11 +61,8 @@
 
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-	if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no])) {
-		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-		return 0;
-	}
+	if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
+		return -ENOENT;
 	ap->cbl = ATA_CBL_PATA40;
 	return ata_std_prereset(ap);
 }
@@ -74,7 +71,7 @@
 
 static void triflex_error_handler(struct ata_port *ap)
 {
-	ata_bmdma_drive_eh(ap, triflex_probe_init, ata_std_softreset, NULL, ata_std_postreset);
+	ata_bmdma_drive_eh(ap, triflex_prereset, ata_std_softreset, NULL, ata_std_postreset);
 }
 
 /**
@@ -221,7 +218,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 1b2ff13..7b5dd23 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -60,7 +60,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_via"
-#define DRV_VERSION "0.1.13"
+#define DRV_VERSION "0.1.14"
 
 /*
  *	The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
@@ -155,11 +155,8 @@
 
 		struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-		if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no])) {
-			ata_port_disable(ap);
-			printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-			return 0;
-		}
+		if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no]))
+			return -ENOENT;
 	}
 
 	if ((config->flags & VIA_UDMA) >= VIA_UDMA_66)
@@ -325,7 +322,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer,
 
 	.irq_handler	= ata_interrupt,
@@ -360,7 +357,7 @@
 
 	.qc_prep 	= ata_qc_prep,
 	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
+
 	.data_xfer	= ata_pio_data_xfer_noirq,
 
 	.irq_handler	= ata_interrupt,
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index fdce6e0..c01496d 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -463,6 +463,7 @@
 
 	.qc_prep		= mv_qc_prep_iie,
 	.qc_issue		= mv_qc_issue,
+	.data_xfer		= ata_mmio_data_xfer,
 
 	.eng_timeout		= mv_eng_timeout,
 
diff --git a/drivers/base/class.c b/drivers/base/class.c
index b06b0e2..b32b77f 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -228,7 +228,7 @@
 
 /**
  * class_destroy - destroys a struct class structure
- * @cs: pointer to the struct class that is to be destroyed
+ * @cls: pointer to the struct class that is to be destroyed
  *
  * Note, the pointer to be destroyed must have been created with a call
  * to class_create().
@@ -658,9 +658,9 @@
 
 /**
  * class_device_create - creates a class device and registers it with sysfs
- * @cs: pointer to the struct class that this device should be registered to.
+ * @cls: pointer to the struct class that this device should be registered to.
  * @parent: pointer to the parent struct class_device of this new device, if any.
- * @dev: the dev_t for the char device to be added.
+ * @devt: the dev_t for the char device to be added.
  * @device: a pointer to a struct device that is assiociated with this class device.
  * @fmt: string for the class device's name
  *
@@ -766,7 +766,7 @@
 /**
  * class_device_destroy - removes a class device that was created with class_device_create()
  * @cls: the pointer to the struct class that this device was registered * with.
- * @dev: the dev_t of the device that was previously registered.
+ * @devt: the dev_t of the device that was previously registered.
  *
  * This call unregisters and cleans up a class device that was created with a
  * call to class_device_create()
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 77bf882..1461569 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
+#include <linux/kthread.h>
 
 #include <linux/firmware.h>
 #include "base.h"
@@ -511,7 +512,6 @@
 		WARN_ON(1);
 		return 0;
 	}
-	daemonize("%s/%s", "firmware", fw_work->name);
 	ret = _request_firmware(&fw, fw_work->name, fw_work->device,
 		fw_work->uevent);
 	if (ret < 0)
@@ -546,9 +546,9 @@
 	const char *name, struct device *device, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
+	struct task_struct *task;
 	struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
 						GFP_ATOMIC);
-	int ret;
 
 	if (!fw_work)
 		return -ENOMEM;
@@ -566,14 +566,14 @@
 		.uevent = uevent,
 	};
 
-	ret = kernel_thread(request_firmware_work_func, fw_work,
-			    CLONE_FS | CLONE_FILES);
+	task = kthread_run(request_firmware_work_func, fw_work,
+			    "firmware/%s", name);
 
-	if (ret < 0) {
+	if (IS_ERR(task)) {
 		fw_work->cont(NULL, fw_work->context);
 		module_put(fw_work->module);
 		kfree(fw_work);
-		return ret;
+		return PTR_ERR(task);
 	}
 	return 0;
 }
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index c774121..68b0471 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -72,6 +72,7 @@
 #include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 
@@ -522,15 +523,12 @@
 		goto out;
 	if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
 		goto out;
-	lo->lo_pending++;
 	loop_add_bio(lo, old_bio);
+	wake_up(&lo->lo_event);
 	spin_unlock_irq(&lo->lo_lock);
-	complete(&lo->lo_bh_done);
 	return 0;
 
 out:
-	if (lo->lo_pending == 0)
-		complete(&lo->lo_bh_done);
 	spin_unlock_irq(&lo->lo_lock);
 	bio_io_error(old_bio, old_bio->bi_size);
 	return 0;
@@ -570,14 +568,18 @@
  * to avoid blocking in our make_request_fn. it also does loop decrypting
  * on reads for block backed loop, as that is too heavy to do from
  * b_end_io context where irqs may be disabled.
+ *
+ * Loop explanation:  loop_clr_fd() sets lo_state to Lo_rundown before
+ * calling kthread_stop().  Therefore once kthread_should_stop() is
+ * true, make_request will not place any more requests.  Therefore
+ * once kthread_should_stop() is true and lo_bio is NULL, we are
+ * done with the loop.
  */
 static int loop_thread(void *data)
 {
 	struct loop_device *lo = data;
 	struct bio *bio;
 
-	daemonize("loop%d", lo->lo_number);
-
 	/*
 	 * loop can be used in an encrypted device,
 	 * hence, it mustn't be stopped at all
@@ -587,47 +589,21 @@
 
 	set_user_nice(current, -20);
 
-	lo->lo_state = Lo_bound;
-	lo->lo_pending = 1;
+	while (!kthread_should_stop() || lo->lo_bio) {
 
-	/*
-	 * complete it, we are running
-	 */
-	complete(&lo->lo_done);
+		wait_event_interruptible(lo->lo_event,
+				lo->lo_bio || kthread_should_stop());
 
-	for (;;) {
-		int pending;
-
-		if (wait_for_completion_interruptible(&lo->lo_bh_done))
+		if (!lo->lo_bio)
 			continue;
-
 		spin_lock_irq(&lo->lo_lock);
-
-		/*
-		 * could be completed because of tear-down, not pending work
-		 */
-		if (unlikely(!lo->lo_pending)) {
-			spin_unlock_irq(&lo->lo_lock);
-			break;
-		}
-
 		bio = loop_get_bio(lo);
-		lo->lo_pending--;
-		pending = lo->lo_pending;
 		spin_unlock_irq(&lo->lo_lock);
 
 		BUG_ON(!bio);
 		loop_handle_bio(lo, bio);
-
-		/*
-		 * upped both for pending work and tear-down, lo_pending
-		 * will hit zero then
-		 */
-		if (unlikely(!pending))
-			break;
 	}
 
-	complete(&lo->lo_done);
 	return 0;
 }
 
@@ -840,12 +816,26 @@
 
 	set_blocksize(bdev, lo_blocksize);
 
-	error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
-	if (error < 0)
-		goto out_putf;
-	wait_for_completion(&lo->lo_done);
+	lo->lo_thread = kthread_create(loop_thread, lo, "loop%d",
+						lo->lo_number);
+	if (IS_ERR(lo->lo_thread)) {
+		error = PTR_ERR(lo->lo_thread);
+		goto out_clr;
+	}
+	lo->lo_state = Lo_bound;
+	wake_up_process(lo->lo_thread);
 	return 0;
 
+out_clr:
+	lo->lo_thread = NULL;
+	lo->lo_device = NULL;
+	lo->lo_backing_file = NULL;
+	lo->lo_flags = 0;
+	set_capacity(disks[lo->lo_number], 0);
+	invalidate_bdev(bdev, 0);
+	bd_set_size(bdev, 0);
+	mapping_set_gfp_mask(mapping, lo->old_gfp_mask);
+	lo->lo_state = Lo_unbound;
  out_putf:
 	fput(file);
  out:
@@ -907,12 +897,9 @@
 
 	spin_lock_irq(&lo->lo_lock);
 	lo->lo_state = Lo_rundown;
-	lo->lo_pending--;
-	if (!lo->lo_pending)
-		complete(&lo->lo_bh_done);
 	spin_unlock_irq(&lo->lo_lock);
 
-	wait_for_completion(&lo->lo_done);
+	kthread_stop(lo->lo_thread);
 
 	lo->lo_backing_file = NULL;
 
@@ -925,6 +912,7 @@
 	lo->lo_sizelimit = 0;
 	lo->lo_encrypt_key_size = 0;
 	lo->lo_flags = 0;
+	lo->lo_thread = NULL;
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 	memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
 	memset(lo->lo_file_name, 0, LO_NAME_SIZE);
@@ -1287,9 +1275,9 @@
 		if (!lo->lo_queue)
 			goto out_mem4;
 		mutex_init(&lo->lo_ctl_mutex);
-		init_completion(&lo->lo_done);
-		init_completion(&lo->lo_bh_done);
 		lo->lo_number = i;
+		lo->lo_thread = NULL;
+		init_waitqueue_head(&lo->lo_event);
 		spin_lock_init(&lo->lo_lock);
 		disk->major = LOOP_MAJOR;
 		disk->first_minor = i;
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index d62b49f..45a8f40 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -358,7 +358,7 @@
 static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_scsi_cmd *cmd, struct ub_request *urq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_end_rq(struct request *rq, int uptodate);
+static void ub_end_rq(struct request *rq, unsigned int status);
 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);
@@ -639,9 +639,15 @@
 	struct ub_request *urq;
 	int n_elem;
 
-	if (atomic_read(&sc->poison) || lun->changed) {
+	if (atomic_read(&sc->poison)) {
 		blkdev_dequeue_request(rq);
-		ub_end_rq(rq, 0);
+		ub_end_rq(rq, DID_NO_CONNECT << 16);
+		return 0;
+	}
+
+	if (lun->changed && !blk_pc_request(rq)) {
+		blkdev_dequeue_request(rq);
+		ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
 		return 0;
 	}
 
@@ -693,7 +699,7 @@
 
 drop:
 	ub_put_cmd(lun, cmd);
-	ub_end_rq(rq, 0);
+	ub_end_rq(rq, DID_ERROR << 16);
 	return 0;
 }
 
@@ -761,47 +767,53 @@
 	struct ub_lun *lun = cmd->lun;
 	struct ub_request *urq = cmd->back;
 	struct request *rq;
-	int uptodate;
+	unsigned int scsi_status;
 
 	rq = urq->rq;
 
 	if (cmd->error == 0) {
-		uptodate = 1;
-
 		if (blk_pc_request(rq)) {
 			if (cmd->act_len >= rq->data_len)
 				rq->data_len = 0;
 			else
 				rq->data_len -= cmd->act_len;
 		}
+		scsi_status = 0;
 	} else {
-		uptodate = 0;
-
 		if (blk_pc_request(rq)) {
 			/* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
 			memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
 			rq->sense_len = UB_SENSE_SIZE;
 			if (sc->top_sense[0] != 0)
-				rq->errors = SAM_STAT_CHECK_CONDITION;
+				scsi_status = SAM_STAT_CHECK_CONDITION;
 			else
-				rq->errors = DID_ERROR << 16;
+				scsi_status = DID_ERROR << 16;
 		} else {
 			if (cmd->error == -EIO) {
 				if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
 					return;
 			}
+			scsi_status = SAM_STAT_CHECK_CONDITION;
 		}
 	}
 
 	urq->rq = NULL;
 
 	ub_put_cmd(lun, cmd);
-	ub_end_rq(rq, uptodate);
+	ub_end_rq(rq, scsi_status);
 	blk_start_queue(lun->disk->queue);
 }
 
-static void ub_end_rq(struct request *rq, int uptodate)
+static void ub_end_rq(struct request *rq, unsigned int scsi_status)
 {
+	int uptodate;
+
+	if (scsi_status == 0) {
+		uptodate = 1;
+	} else {
+		uptodate = 0;
+		rq->errors = scsi_status;
+	}
 	end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
 	end_that_request_last(rq, uptodate);
 }
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 23f9621..efcc28e 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -2,7 +2,7 @@
  *
  *  AVM BlueFRITZ! USB driver
  *
- *  Copyright (C) 2003  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2003-2006  Marcel Holtmann <marcel@holtmann.org>
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -59,7 +59,6 @@
 
 MODULE_DEVICE_TABLE(usb, bfusb_table);
 
-
 #define BFUSB_MAX_BLOCK_SIZE	256
 
 #define BFUSB_BLOCK_TIMEOUT	3000
@@ -70,7 +69,7 @@
 #define BFUSB_MAX_BULK_TX	2
 #define BFUSB_MAX_BULK_RX	2
 
-struct bfusb {
+struct bfusb_data {
 	struct hci_dev		*hdev;
 
 	unsigned long		state;
@@ -92,137 +91,136 @@
 	struct sk_buff_head	completed_q;
 };
 
-struct bfusb_scb {
+struct bfusb_data_scb {
 	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 struct urb *bfusb_get_completed(struct bfusb *bfusb)
+static struct urb *bfusb_get_completed(struct bfusb_data *data)
 {
 	struct sk_buff *skb;
 	struct urb *urb = NULL;
 
-	BT_DBG("bfusb %p", bfusb);
+	BT_DBG("bfusb %p", data);
 
-	skb = skb_dequeue(&bfusb->completed_q);
+	skb = skb_dequeue(&data->completed_q);
 	if (skb) {
-		urb = ((struct bfusb_scb *) skb->cb)->urb;
+		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
 		kfree_skb(skb);
 	}
 
 	return urb;
 }
 
-static void bfusb_unlink_urbs(struct bfusb *bfusb)
+static void bfusb_unlink_urbs(struct bfusb_data *data)
 {
 	struct sk_buff *skb;
 	struct urb *urb;
 
-	BT_DBG("bfusb %p", bfusb);
+	BT_DBG("bfusb %p", data);
 
-	while ((skb = skb_dequeue(&bfusb->pending_q))) {
-		urb = ((struct bfusb_scb *) skb->cb)->urb;
+	while ((skb = skb_dequeue(&data->pending_q))) {
+		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
 		usb_kill_urb(urb);
-		skb_queue_tail(&bfusb->completed_q, skb);
+		skb_queue_tail(&data->completed_q, skb);
 	}
 
-	while ((urb = bfusb_get_completed(bfusb)))
+	while ((urb = bfusb_get_completed(data)))
 		usb_free_urb(urb);
 }
 
-
-static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb)
+static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
 {
-	struct bfusb_scb *scb = (void *) skb->cb;
-	struct urb *urb = bfusb_get_completed(bfusb);
+	struct bfusb_data_scb *scb = (void *) skb->cb;
+	struct urb *urb = bfusb_get_completed(data);
 	int err, pipe;
 
-	BT_DBG("bfusb %p skb %p len %d", bfusb, skb, skb->len);
+	BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
 
 	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
 		return -ENOMEM;
 
-	pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
+	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
 
-	usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, skb->len,
+	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len,
 			bfusb_tx_complete, skb);
 
 	scb->urb = urb;
 
-	skb_queue_tail(&bfusb->pending_q, skb);
+	skb_queue_tail(&data->pending_q, skb);
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err) {
 		BT_ERR("%s bulk tx submit failed urb %p err %d", 
-					bfusb->hdev->name, urb, err);
-		skb_unlink(skb, &bfusb->pending_q);
+					data->hdev->name, urb, err);
+		skb_unlink(skb, &data->pending_q);
 		usb_free_urb(urb);
 	} else
-		atomic_inc(&bfusb->pending_tx);
+		atomic_inc(&data->pending_tx);
 
 	return err;
 }
 
-static void bfusb_tx_wakeup(struct bfusb *bfusb)
+static void bfusb_tx_wakeup(struct bfusb_data *data)
 {
 	struct sk_buff *skb;
 
-	BT_DBG("bfusb %p", bfusb);
+	BT_DBG("bfusb %p", data);
 
-	if (test_and_set_bit(BFUSB_TX_PROCESS, &bfusb->state)) {
-		set_bit(BFUSB_TX_WAKEUP, &bfusb->state);
+	if (test_and_set_bit(BFUSB_TX_PROCESS, &data->state)) {
+		set_bit(BFUSB_TX_WAKEUP, &data->state);
 		return;
 	}
 
 	do {
-		clear_bit(BFUSB_TX_WAKEUP, &bfusb->state);
+		clear_bit(BFUSB_TX_WAKEUP, &data->state);
 
-		while ((atomic_read(&bfusb->pending_tx) < BFUSB_MAX_BULK_TX) &&
-				(skb = skb_dequeue(&bfusb->transmit_q))) {
-			if (bfusb_send_bulk(bfusb, skb) < 0) {
-				skb_queue_head(&bfusb->transmit_q, skb);
+		while ((atomic_read(&data->pending_tx) < BFUSB_MAX_BULK_TX) &&
+				(skb = skb_dequeue(&data->transmit_q))) {
+			if (bfusb_send_bulk(data, skb) < 0) {
+				skb_queue_head(&data->transmit_q, skb);
 				break;
 			}
 		}
 
-	} while (test_bit(BFUSB_TX_WAKEUP, &bfusb->state));
+	} while (test_bit(BFUSB_TX_WAKEUP, &data->state));
 
-	clear_bit(BFUSB_TX_PROCESS, &bfusb->state);
+	clear_bit(BFUSB_TX_PROCESS, &data->state);
 }
 
 static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
-	struct bfusb *bfusb = (struct bfusb *) skb->dev;
+	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
 
-	BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
+	BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
 
-	atomic_dec(&bfusb->pending_tx);
+	atomic_dec(&data->pending_tx);
 
-	if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
+	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
 		return;
 
 	if (!urb->status)
-		bfusb->hdev->stat.byte_tx += skb->len;
+		data->hdev->stat.byte_tx += skb->len;
 	else
-		bfusb->hdev->stat.err_tx++;
+		data->hdev->stat.err_tx++;
 
-	read_lock(&bfusb->lock);
+	read_lock(&data->lock);
 
-	skb_unlink(skb, &bfusb->pending_q);
-	skb_queue_tail(&bfusb->completed_q, skb);
+	skb_unlink(skb, &data->pending_q);
+	skb_queue_tail(&data->completed_q, skb);
 
-	bfusb_tx_wakeup(bfusb);
+	bfusb_tx_wakeup(data);
 
-	read_unlock(&bfusb->lock);
+	read_unlock(&data->lock);
 }
 
 
-static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
+static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
 {
-	struct bfusb_scb *scb;
+	struct bfusb_data_scb *scb;
 	struct sk_buff *skb;
 	int err, pipe, size = HCI_MAX_FRAME_SIZE + 32;
 
@@ -231,28 +229,29 @@
 	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
 		return -ENOMEM;
 
-	if (!(skb = bt_skb_alloc(size, GFP_ATOMIC))) {
+	skb = bt_skb_alloc(size, GFP_ATOMIC);
+	if (!skb) {
 		usb_free_urb(urb);
 		return -ENOMEM;
 	}
 
-	skb->dev = (void *) bfusb;
+	skb->dev = (void *) data;
 
-	scb = (struct bfusb_scb *) skb->cb;
+	scb = (struct bfusb_data_scb *) skb->cb;
 	scb->urb = urb;
 
-	pipe = usb_rcvbulkpipe(bfusb->udev, bfusb->bulk_in_ep);
+	pipe = usb_rcvbulkpipe(data->udev, data->bulk_in_ep);
 
-	usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, size,
+	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, size,
 			bfusb_rx_complete, skb);
 
-	skb_queue_tail(&bfusb->pending_q, skb);
+	skb_queue_tail(&data->pending_q, skb);
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err) {
 		BT_ERR("%s bulk rx submit failed urb %p err %d",
-					bfusb->hdev->name, urb, err);
-		skb_unlink(skb, &bfusb->pending_q);
+					data->hdev->name, urb, err);
+		skb_unlink(skb, &data->pending_q);
 		kfree_skb(skb);
 		usb_free_urb(urb);
 	}
@@ -260,15 +259,15 @@
 	return err;
 }
 
-static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *data, int len)
+static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len)
 {
-	BT_DBG("bfusb %p hdr 0x%02x data %p len %d", bfusb, hdr, data, len);
+	BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len);
 
 	if (hdr & 0x10) {
-		BT_ERR("%s error in block", bfusb->hdev->name);
-		if (bfusb->reassembly)
-			kfree_skb(bfusb->reassembly);
-		bfusb->reassembly = NULL;
+		BT_ERR("%s error in block", data->hdev->name);
+		if (data->reassembly)
+			kfree_skb(data->reassembly);
+		data->reassembly = NULL;
 		return -EIO;
 	}
 
@@ -277,46 +276,46 @@
 		unsigned char pkt_type;
 		int pkt_len = 0;
 
-		if (bfusb->reassembly) {
-			BT_ERR("%s unexpected start block", bfusb->hdev->name);
-			kfree_skb(bfusb->reassembly);
-			bfusb->reassembly = NULL;
+		if (data->reassembly) {
+			BT_ERR("%s unexpected start block", data->hdev->name);
+			kfree_skb(data->reassembly);
+			data->reassembly = NULL;
 		}
 
 		if (len < 1) {
-			BT_ERR("%s no packet type found", bfusb->hdev->name);
+			BT_ERR("%s no packet type found", data->hdev->name);
 			return -EPROTO;
 		}
 
-		pkt_type = *data++; len--;
+		pkt_type = *buf++; len--;
 
 		switch (pkt_type) {
 		case HCI_EVENT_PKT:
 			if (len >= HCI_EVENT_HDR_SIZE) {
-				struct hci_event_hdr *hdr = (struct hci_event_hdr *) data;
+				struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf;
 				pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
 			} else {
-				BT_ERR("%s event block is too short", bfusb->hdev->name);
+				BT_ERR("%s event block is too short", data->hdev->name);
 				return -EILSEQ;
 			}
 			break;
 
 		case HCI_ACLDATA_PKT:
 			if (len >= HCI_ACL_HDR_SIZE) {
-				struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) data;
+				struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf;
 				pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen);
 			} else {
-				BT_ERR("%s data block is too short", bfusb->hdev->name);
+				BT_ERR("%s data block is too short", data->hdev->name);
 				return -EILSEQ;
 			}
 			break;
 
 		case HCI_SCODATA_PKT:
 			if (len >= HCI_SCO_HDR_SIZE) {
-				struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) data;
+				struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf;
 				pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
 			} else {
-				BT_ERR("%s audio block is too short", bfusb->hdev->name);
+				BT_ERR("%s audio block is too short", data->hdev->name);
 				return -EILSEQ;
 			}
 			break;
@@ -324,27 +323,27 @@
 
 		skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
 		if (!skb) {
-			BT_ERR("%s no memory for the packet", bfusb->hdev->name);
+			BT_ERR("%s no memory for the packet", data->hdev->name);
 			return -ENOMEM;
 		}
 
-		skb->dev = (void *) bfusb->hdev;
+		skb->dev = (void *) data->hdev;
 		bt_cb(skb)->pkt_type = pkt_type;
 
-		bfusb->reassembly = skb;
+		data->reassembly = skb;
 	} else {
-		if (!bfusb->reassembly) {
-			BT_ERR("%s unexpected continuation block", bfusb->hdev->name);
+		if (!data->reassembly) {
+			BT_ERR("%s unexpected continuation block", data->hdev->name);
 			return -EIO;
 		}
 	}
 
 	if (len > 0)
-		memcpy(skb_put(bfusb->reassembly, len), data, len);
+		memcpy(skb_put(data->reassembly, len), buf, len);
 
 	if (hdr & 0x08) {
-		hci_recv_frame(bfusb->reassembly);
-		bfusb->reassembly = NULL;
+		hci_recv_frame(data->reassembly);
+		data->reassembly = NULL;
 	}
 
 	return 0;
@@ -353,22 +352,22 @@
 static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
-	struct bfusb *bfusb = (struct bfusb *) skb->dev;
+	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
 	unsigned char *buf = urb->transfer_buffer;
 	int count = urb->actual_length;
 	int err, hdr, len;
 
 	BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
 
-	read_lock(&bfusb->lock);
+	read_lock(&data->lock);
 
-	if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
+	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
 		goto unlock;
 
 	if (urb->status || !count)
 		goto resubmit;
 
-	bfusb->hdev->stat.byte_rx += count;
+	data->hdev->stat.byte_rx += count;
 
 	skb_put(skb, count);
 
@@ -387,90 +386,89 @@
 
 		if (count < len) {
 			BT_ERR("%s block extends over URB buffer ranges",
-					bfusb->hdev->name);
+					data->hdev->name);
 		}
 
 		if ((hdr & 0xe1) == 0xc1)
-			bfusb_recv_block(bfusb, hdr, buf, len);
+			bfusb_recv_block(data, hdr, buf, len);
 
 		count -= len;
 		buf   += len;
 	}
 
-	skb_unlink(skb, &bfusb->pending_q);
+	skb_unlink(skb, &data->pending_q);
 	kfree_skb(skb);
 
-	bfusb_rx_submit(bfusb, urb);
+	bfusb_rx_submit(data, urb);
 
-	read_unlock(&bfusb->lock);
+	read_unlock(&data->lock);
 
 	return;
 
 resubmit:
-	urb->dev = bfusb->udev;
+	urb->dev = data->udev;
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err) {
 		BT_ERR("%s bulk resubmit failed urb %p err %d",
-					bfusb->hdev->name, urb, err);
+					data->hdev->name, urb, err);
 	}
 
 unlock:
-	read_unlock(&bfusb->lock);
+	read_unlock(&data->lock);
 }
 
-
 static int bfusb_open(struct hci_dev *hdev)
 {
-	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+	struct bfusb_data *data = hdev->driver_data;
 	unsigned long flags;
 	int i, err;
 
-	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+	BT_DBG("hdev %p bfusb %p", hdev, data);
 
 	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
 		return 0;
 
-	write_lock_irqsave(&bfusb->lock, flags);
+	write_lock_irqsave(&data->lock, flags);
 
-	err = bfusb_rx_submit(bfusb, NULL);
+	err = bfusb_rx_submit(data, NULL);
 	if (!err) {
 		for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
-			bfusb_rx_submit(bfusb, NULL);
+			bfusb_rx_submit(data, NULL);
 	} else {
 		clear_bit(HCI_RUNNING, &hdev->flags);
 	}
 
-	write_unlock_irqrestore(&bfusb->lock, flags);
+	write_unlock_irqrestore(&data->lock, flags);
 
 	return err;
 }
 
 static int bfusb_flush(struct hci_dev *hdev)
 {
-	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+	struct bfusb_data *data = hdev->driver_data;
 
-	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+	BT_DBG("hdev %p bfusb %p", hdev, data);
 
-	skb_queue_purge(&bfusb->transmit_q);
+	skb_queue_purge(&data->transmit_q);
 
 	return 0;
 }
 
 static int bfusb_close(struct hci_dev *hdev)
 {
-	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+	struct bfusb_data *data = hdev->driver_data;
 	unsigned long flags;
 
-	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+	BT_DBG("hdev %p bfusb %p", hdev, data);
 
 	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
 		return 0;
 
-	write_lock_irqsave(&bfusb->lock, flags);
-	write_unlock_irqrestore(&bfusb->lock, flags);
+	write_lock_irqsave(&data->lock, flags);
+	write_unlock_irqrestore(&data->lock, flags);
 
-	bfusb_unlink_urbs(bfusb);
+	bfusb_unlink_urbs(data);
 	bfusb_flush(hdev);
 
 	return 0;
@@ -479,7 +477,7 @@
 static int bfusb_send_frame(struct sk_buff *skb)
 {
 	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
-	struct bfusb *bfusb;
+	struct bfusb_data *data;
 	struct sk_buff *nskb;
 	unsigned char buf[3];
 	int sent = 0, size, count;
@@ -494,7 +492,7 @@
 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return -EBUSY;
 
-	bfusb = (struct bfusb *) hdev->driver_data;
+	data = hdev->driver_data;
 
 	switch (bt_cb(skb)->pkt_type) {
 	case HCI_COMMAND_PKT:
@@ -514,12 +512,13 @@
 	count = skb->len;
 
 	/* Max HCI frame size seems to be 1511 + 1 */
-	if (!(nskb = bt_skb_alloc(count + 32, GFP_ATOMIC))) {
+	nskb = bt_skb_alloc(count + 32, GFP_ATOMIC);
+	if (!nskb) {
 		BT_ERR("Can't allocate memory for new packet");
 		return -ENOMEM;
 	}
 
-	nskb->dev = (void *) bfusb;
+	nskb->dev = (void *) data;
 
 	while (count) {
 		size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE);
@@ -536,18 +535,18 @@
 	}
 
 	/* Don't send frame with multiple size of bulk max packet */
-	if ((nskb->len % bfusb->bulk_pkt_size) == 0) {
+	if ((nskb->len % data->bulk_pkt_size) == 0) {
 		buf[0] = 0xdd;
 		buf[1] = 0x00;
 		memcpy(skb_put(nskb, 2), buf, 2);
 	}
 
-	read_lock(&bfusb->lock);
+	read_lock(&data->lock);
 
-	skb_queue_tail(&bfusb->transmit_q, nskb);
-	bfusb_tx_wakeup(bfusb);
+	skb_queue_tail(&data->transmit_q, nskb);
+	bfusb_tx_wakeup(data);
 
-	read_unlock(&bfusb->lock);
+	read_unlock(&data->lock);
 
 	kfree_skb(skb);
 
@@ -556,11 +555,11 @@
 
 static void bfusb_destruct(struct hci_dev *hdev)
 {
-	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+	struct bfusb_data *data = hdev->driver_data;
 
-	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+	BT_DBG("hdev %p bfusb %p", hdev, data);
 
-	kfree(bfusb);
+	kfree(data);
 }
 
 static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
@@ -568,25 +567,24 @@
 	return -ENOIOCTLCMD;
 }
 
-
-static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int count)
+static int bfusb_load_firmware(struct bfusb_data *data, unsigned char *firmware, int count)
 {
 	unsigned char *buf;
 	int err, pipe, len, size, sent = 0;
 
-	BT_DBG("bfusb %p udev %p", bfusb, bfusb->udev);
+	BT_DBG("bfusb %p udev %p", data, data->udev);
 
 	BT_INFO("BlueFRITZ! USB loading firmware");
 
-	pipe = usb_sndctrlpipe(bfusb->udev, 0);
+	pipe = usb_sndctrlpipe(data->udev, 0);
 
-	if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
+	if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
 				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
 		BT_ERR("Can't change to loading configuration");
 		return -EBUSY;
 	}
 
-	bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
+	data->udev->toggle[0] = data->udev->toggle[1] = 0;
 
 	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
 	if (!buf) {
@@ -594,14 +592,14 @@
 		return -ENOMEM;
 	}
 
-	pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
+	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
 
 	while (count) {
 		size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3);
 
 		memcpy(buf, firmware + sent, size);
 
-		err = usb_bulk_msg(bfusb->udev, pipe, buf, size,
+		err = usb_bulk_msg(data->udev, pipe, buf, size,
 					&len, BFUSB_BLOCK_TIMEOUT);
 
 		if (err || (len != size)) {
@@ -613,21 +611,23 @@
 		count -= size;
 	}
 
-	if ((err = usb_bulk_msg(bfusb->udev, pipe, NULL, 0,
-				&len, BFUSB_BLOCK_TIMEOUT)) < 0) {
+	err = usb_bulk_msg(data->udev, pipe, NULL, 0,
+					&len, BFUSB_BLOCK_TIMEOUT);
+	if (err < 0) {
 		BT_ERR("Error in null packet request");
 		goto error;
 	}
 
-	pipe = usb_sndctrlpipe(bfusb->udev, 0);
+	pipe = usb_sndctrlpipe(data->udev, 0);
 
-        if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
-				0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+	err = usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
+				0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+	if (err < 0) {
 		BT_ERR("Can't change to running configuration");
 		goto error;
 	}
 
-	bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
+	data->udev->toggle[0] = data->udev->toggle[1] = 0;
 
 	BT_INFO("BlueFRITZ! USB device ready");
 
@@ -637,9 +637,9 @@
 error:
 	kfree(buf);
 
-	pipe = usb_sndctrlpipe(bfusb->udev, 0);
+	pipe = usb_sndctrlpipe(data->udev, 0);
 
-	usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
+	usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
 				0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 
 	return err;
@@ -652,7 +652,7 @@
 	struct usb_host_endpoint *bulk_out_ep;
 	struct usb_host_endpoint *bulk_in_ep;
 	struct hci_dev *hdev;
-	struct bfusb *bfusb;
+	struct bfusb_data *data;
 
 	BT_DBG("intf %p id %p", intf, id);
 
@@ -672,23 +672,24 @@
 	}
 
 	/* Initialize control structure and load firmware */
-	if (!(bfusb = kzalloc(sizeof(struct bfusb), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
+	if (!data) {
 		BT_ERR("Can't allocate memory for control structure");
 		goto done;
 	}
 
-	bfusb->udev = udev;
-	bfusb->bulk_in_ep    = bulk_in_ep->desc.bEndpointAddress;
-	bfusb->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
-	bfusb->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
+	data->udev = udev;
+	data->bulk_in_ep    = bulk_in_ep->desc.bEndpointAddress;
+	data->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
+	data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
 
-	rwlock_init(&bfusb->lock);
+	rwlock_init(&data->lock);
 
-	bfusb->reassembly = NULL;
+	data->reassembly = NULL;
 
-	skb_queue_head_init(&bfusb->transmit_q);
-	skb_queue_head_init(&bfusb->pending_q);
-	skb_queue_head_init(&bfusb->completed_q);
+	skb_queue_head_init(&data->transmit_q);
+	skb_queue_head_init(&data->pending_q);
+	skb_queue_head_init(&data->completed_q);
 
 	if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
 		BT_ERR("Firmware request failed");
@@ -697,7 +698,7 @@
 
 	BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
 
-	if (bfusb_load_firmware(bfusb, firmware->data, firmware->size) < 0) {
+	if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) {
 		BT_ERR("Firmware loading failed");
 		goto release;
 	}
@@ -711,10 +712,10 @@
 		goto error;
 	}
 
-	bfusb->hdev = hdev;
+	data->hdev = hdev;
 
 	hdev->type = HCI_USB;
-	hdev->driver_data = bfusb;
+	hdev->driver_data = data;
 	SET_HCIDEV_DEV(hdev, &intf->dev);
 
 	hdev->open     = bfusb_open;
@@ -732,7 +733,7 @@
 		goto error;
 	}
 
-	usb_set_intfdata(intf, bfusb);
+	usb_set_intfdata(intf, data);
 
 	return 0;
 
@@ -740,7 +741,7 @@
 	release_firmware(firmware);
 
 error:
-	kfree(bfusb);
+	kfree(data);
 
 done:
 	return -EIO;
@@ -748,8 +749,8 @@
 
 static void bfusb_disconnect(struct usb_interface *intf)
 {
-	struct bfusb *bfusb = usb_get_intfdata(intf);
-	struct hci_dev *hdev = bfusb->hdev;
+	struct bfusb_data *data = usb_get_intfdata(intf);
+	struct hci_dev *hdev = data->hdev;
 
 	BT_DBG("intf %p", intf);
 
@@ -779,7 +780,8 @@
 
 	BT_INFO("BlueFRITZ! USB driver ver %s", VERSION);
 
-	if ((err = usb_register(&bfusb_driver)) < 0)
+	err = usb_register(&bfusb_driver);
+	if (err < 0)
 		BT_ERR("Failed to register BlueFRITZ! USB driver");
 
 	return err;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 93ba25b..420b645 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -241,15 +241,11 @@
 
 static void hci_uart_destruct(struct hci_dev *hdev)
 {
-	struct hci_uart *hu;
-
 	if (!hdev)
 		return;
 
 	BT_DBG("%s", hdev->name);
-
-	hu = (struct hci_uart *) hdev->driver_data;
-	kfree(hu);
+	kfree(hdev->driver_data);
 }
 
 /* ------ LDISC part ------ */
@@ -272,7 +268,7 @@
 		return -EEXIST;
 
 	if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
-		BT_ERR("Can't allocate controll structure");
+		BT_ERR("Can't allocate control structure");
 		return -ENFILE;
 	}
 
@@ -360,7 +356,7 @@
  *     
  * Return Value:    None
  */
-static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
+static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
 {
 	struct hci_uart *hu = (void *)tty->disc_data;
 
@@ -375,7 +371,8 @@
 	hu->hdev->stat.byte_rx += count;
 	spin_unlock(&hu->rx_lock);
 
-	if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver->unthrottle)
+	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+					tty->driver->unthrottle)
 		tty->driver->unthrottle(tty);
 }
 
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index e2d4bea..0801af4 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -96,6 +96,9 @@
 	/* Ericsson with non-standard id */
 	{ USB_DEVICE(0x0bdb, 0x1002) },
 
+	/* Canyon CN-BTU1 with HID interfaces */
+	{ USB_DEVICE(0x0c10, 0x0000), .driver_info = HCI_RESET },
+
 	{ }	/* Terminating entry */
 };
 
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index aac67a3a..a278d98 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -2,9 +2,9 @@
  *
  *  Bluetooth virtual HCI driver
  *
- *  Copyright (C) 2000-2001 Qualcomm Incorporated
- *  Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
- *  Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2000-2001  Qualcomm Incorporated
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -72,21 +72,21 @@
 
 static int vhci_close_dev(struct hci_dev *hdev)
 {
-	struct vhci_data *vhci = hdev->driver_data;
+	struct vhci_data *data = hdev->driver_data;
 
 	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
 		return 0;
 
-	skb_queue_purge(&vhci->readq);
+	skb_queue_purge(&data->readq);
 
 	return 0;
 }
 
 static int vhci_flush(struct hci_dev *hdev)
 {
-	struct vhci_data *vhci = hdev->driver_data;
+	struct vhci_data *data = hdev->driver_data;
 
-	skb_queue_purge(&vhci->readq);
+	skb_queue_purge(&data->readq);
 
 	return 0;
 }
@@ -94,7 +94,7 @@
 static int vhci_send_frame(struct sk_buff *skb)
 {
 	struct hci_dev* hdev = (struct hci_dev *) skb->dev;
-	struct vhci_data *vhci;
+	struct vhci_data *data;
 
 	if (!hdev) {
 		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
@@ -104,15 +104,15 @@
 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return -EBUSY;
 
-	vhci = hdev->driver_data;
+	data = hdev->driver_data;
 
 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
-	skb_queue_tail(&vhci->readq, skb);
+	skb_queue_tail(&data->readq, skb);
 
-	if (vhci->flags & VHCI_FASYNC)
-		kill_fasync(&vhci->fasync, SIGIO, POLL_IN);
+	if (data->flags & VHCI_FASYNC)
+		kill_fasync(&data->fasync, SIGIO, POLL_IN);
 
-	wake_up_interruptible(&vhci->read_wait);
+	wake_up_interruptible(&data->read_wait);
 
 	return 0;
 }
@@ -122,7 +122,7 @@
 	kfree(hdev->driver_data);
 }
 
-static inline ssize_t vhci_get_user(struct vhci_data *vhci,
+static inline ssize_t vhci_get_user(struct vhci_data *data,
 					const char __user *buf, size_t count)
 {
 	struct sk_buff *skb;
@@ -139,7 +139,7 @@
 		return -EFAULT;
 	}
 
-	skb->dev = (void *) vhci->hdev;
+	skb->dev = (void *) data->hdev;
 	bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
 	skb_pull(skb, 1);
 
@@ -148,7 +148,7 @@
 	return count;
 }
 
-static inline ssize_t vhci_put_user(struct vhci_data *vhci,
+static inline ssize_t vhci_put_user(struct vhci_data *data,
 			struct sk_buff *skb, char __user *buf, int count)
 {
 	char __user *ptr = buf;
@@ -161,42 +161,43 @@
 
 	total += len;
 
-	vhci->hdev->stat.byte_tx += len;
+	data->hdev->stat.byte_tx += len;
 
 	switch (bt_cb(skb)->pkt_type) {
 	case HCI_COMMAND_PKT:
-		vhci->hdev->stat.cmd_tx++;
+		data->hdev->stat.cmd_tx++;
 		break;
 
 	case HCI_ACLDATA_PKT:
-		vhci->hdev->stat.acl_tx++;
+		data->hdev->stat.acl_tx++;
 		break;
 
 	case HCI_SCODATA_PKT:
-		vhci->hdev->stat.cmd_tx++;
+		data->hdev->stat.cmd_tx++;
 		break;
 	};
 
 	return total;
 }
 
-static loff_t vhci_llseek(struct file * file, loff_t offset, int origin)
+static loff_t vhci_llseek(struct file *file, loff_t offset, int origin)
 {
 	return -ESPIPE;
 }
 
-static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
+static ssize_t vhci_read(struct file *file,
+				char __user *buf, size_t count, loff_t *pos)
 {
 	DECLARE_WAITQUEUE(wait, current);
-	struct vhci_data *vhci = file->private_data;
+	struct vhci_data *data = file->private_data;
 	struct sk_buff *skb;
 	ssize_t ret = 0;
 
-	add_wait_queue(&vhci->read_wait, &wait);
+	add_wait_queue(&data->read_wait, &wait);
 	while (count) {
 		set_current_state(TASK_INTERRUPTIBLE);
 
-		skb = skb_dequeue(&vhci->readq);
+		skb = skb_dequeue(&data->readq);
 		if (!skb) {
 			if (file->f_flags & O_NONBLOCK) {
 				ret = -EAGAIN;
@@ -213,7 +214,7 @@
 		}
 
 		if (access_ok(VERIFY_WRITE, buf, count))
-			ret = vhci_put_user(vhci, skb, buf, count);
+			ret = vhci_put_user(data, skb, buf, count);
 		else
 			ret = -EFAULT;
 
@@ -221,7 +222,7 @@
 		break;
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&vhci->read_wait, &wait);
+	remove_wait_queue(&data->read_wait, &wait);
 
 	return ret;
 }
@@ -229,21 +230,21 @@
 static ssize_t vhci_write(struct file *file,
 			const char __user *buf, size_t count, loff_t *pos)
 {
-	struct vhci_data *vhci = file->private_data;
+	struct vhci_data *data = file->private_data;
 
 	if (!access_ok(VERIFY_READ, buf, count))
 		return -EFAULT;
 
-	return vhci_get_user(vhci, buf, count);
+	return vhci_get_user(data, buf, count);
 }
 
 static unsigned int vhci_poll(struct file *file, poll_table *wait)
 {
-	struct vhci_data *vhci = file->private_data;
+	struct vhci_data *data = file->private_data;
 
-	poll_wait(file, &vhci->read_wait, wait);
+	poll_wait(file, &data->read_wait, wait);
 
-	if (!skb_queue_empty(&vhci->readq))
+	if (!skb_queue_empty(&data->readq))
 		return POLLIN | POLLRDNORM;
 
 	return POLLOUT | POLLWRNORM;
@@ -257,26 +258,26 @@
 
 static int vhci_open(struct inode *inode, struct file *file)
 {
-	struct vhci_data *vhci;
+	struct vhci_data *data;
 	struct hci_dev *hdev;
 
-	vhci = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
-	if (!vhci)
+	data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
 
-	skb_queue_head_init(&vhci->readq);
-	init_waitqueue_head(&vhci->read_wait);
+	skb_queue_head_init(&data->readq);
+	init_waitqueue_head(&data->read_wait);
 
 	hdev = hci_alloc_dev();
 	if (!hdev) {
-		kfree(vhci);
+		kfree(data);
 		return -ENOMEM;
 	}
 
-	vhci->hdev = hdev;
+	data->hdev = hdev;
 
-	hdev->type = HCI_VHCI;
-	hdev->driver_data = vhci;
+	hdev->type = HCI_VIRTUAL;
+	hdev->driver_data = data;
 
 	hdev->open     = vhci_open_dev;
 	hdev->close    = vhci_close_dev;
@@ -288,20 +289,20 @@
 
 	if (hci_register_dev(hdev) < 0) {
 		BT_ERR("Can't register HCI device");
-		kfree(vhci);
+		kfree(data);
 		hci_free_dev(hdev);
 		return -EBUSY;
 	}
 
-	file->private_data = vhci;
+	file->private_data = data;
 
 	return nonseekable_open(inode, file);
 }
 
 static int vhci_release(struct inode *inode, struct file *file)
 {
-	struct vhci_data *vhci = file->private_data;
-	struct hci_dev *hdev = vhci->hdev;
+	struct vhci_data *data = file->private_data;
+	struct hci_dev *hdev = data->hdev;
 
 	if (hci_unregister_dev(hdev) < 0) {
 		BT_ERR("Can't unregister HCI device %s", hdev->name);
@@ -316,17 +317,17 @@
 
 static int vhci_fasync(int fd, struct file *file, int on)
 {
-	struct vhci_data *vhci = file->private_data;
+	struct vhci_data *data = file->private_data;
 	int err;
 
-	err = fasync_helper(fd, file, on, &vhci->fasync);
+	err = fasync_helper(fd, file, on, &data->fasync);
 	if (err < 0)
 		return err;
 
 	if (on)
-		vhci->flags |= VHCI_FASYNC;
+		data->flags |= VHCI_FASYNC;
 	else
-		vhci->flags &= ~VHCI_FASYNC;
+		data->flags &= ~VHCI_FASYNC;
 
 	return 0;
 }
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 1b21c3a..4cc619e 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -831,14 +831,6 @@
 	  will get access to the real time clock (or hardware clock) built
 	  into your computer.
 
-config S3C2410_RTC
-	bool "S3C2410 RTC Driver"
-	depends on ARCH_S3C2410
-	help
-	  RTC (Realtime Clock) driver for the clock inbuilt into the
-	  Samsung S3C2410. This can provide periodic interrupt rates
-	  from 1Hz to 64Hz for user programs, and wakeup from Alarm.
-
 config COBALT_LCD
 	bool "Support for Cobalt LCD"
 	depends on MIPS_COBALT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index b583d0c..19114df 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -69,7 +69,6 @@
 obj-$(CONFIG_SGI_DS1286)	+= ds1286.o
 obj-$(CONFIG_SGI_IP27_RTC)	+= ip27-rtc.o
 obj-$(CONFIG_DS1302)		+= ds1302.o
-obj-$(CONFIG_S3C2410_RTC)	+= s3c2410-rtc.o
 ifeq ($(CONFIG_GENERIC_NVRAM),y)
   obj-$(CONFIG_NVRAM)	+= generic_nvram.o
 else
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 5e59c0b..4711d9b 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -746,11 +746,9 @@
 		gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
 	}
 
-#if 0
 	/* This is an optimization that is only allowed for dumb cards */
 	/* Smart cards require knowledge of iflags and oflags too: that 
 	   might change hardware cooking mode.... */
-#endif
 	if (old_termios) {
 		if(   (tiosp->c_iflag == old_termios->c_iflag)
 		   && (tiosp->c_oflag == old_termios->c_oflag)
@@ -774,14 +772,7 @@
 		if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
 	}
 
-	baudrate = tiosp->c_cflag & CBAUD;
-	if (baudrate & CBAUDEX) {
-		baudrate &= ~CBAUDEX;
-		if ((baudrate < 1) || (baudrate > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			baudrate += 15;
-	}
+	baudrate = tty_get_baud_rate(tty);
 
 	baudrate = gs_baudrates[baudrate];
 	if ((tiosp->c_cflag & CBAUD) == B38400) {
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index ccd7e71..8efbc9c 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -50,6 +50,43 @@
 #define INTEL_RNG_ADDR_LEN			3
 
 /*
+ * LPC bridge PCI config space registers
+ */
+#define FWH_DEC_EN1_REG_OLD			0xe3
+#define FWH_DEC_EN1_REG_NEW			0xd9 /* high byte of 16-bit register */
+#define FWH_F8_EN_MASK				0x80
+
+#define BIOS_CNTL_REG_OLD			0x4e
+#define BIOS_CNTL_REG_NEW			0xdc
+#define BIOS_CNTL_WRITE_ENABLE_MASK		0x01
+#define BIOS_CNTL_LOCK_ENABLE_MASK		0x02
+
+/*
+ * Magic address at which Intel Firmware Hubs get accessed
+ */
+#define INTEL_FWH_ADDR				0xffff0000
+#define INTEL_FWH_ADDR_LEN			2
+
+/*
+ * Intel Firmware Hub command codes (write to any address inside the device)
+ */
+#define INTEL_FWH_RESET_CMD			0xff /* aka READ_ARRAY */
+#define INTEL_FWH_READ_ID_CMD			0x90
+
+/*
+ * Intel Firmware Hub Read ID command result addresses
+ */
+#define INTEL_FWH_MANUFACTURER_CODE_ADDRESS	0x000000
+#define INTEL_FWH_DEVICE_CODE_ADDRESS		0x000001
+
+/*
+ * Intel Firmware Hub Read ID command result values
+ */
+#define INTEL_FWH_MANUFACTURER_CODE		0x89
+#define INTEL_FWH_DEVICE_CODE_8M		0xac
+#define INTEL_FWH_DEVICE_CODE_4M		0xad
+
+/*
  * Data for PCI driver interface
  *
  * This data only exists for exporting the supported
@@ -58,12 +95,50 @@
  * want to register another driver on the same PCI id.
  */
 static const struct pci_device_id pci_tbl[] = {
-	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+/* AA
+	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+	{ 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */
+/* AB
+	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+	{ 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */
+/* ??
+	{ 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+/* BAM, CAM, DBM, FBM, GxM
+	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+	{ 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */
+	{ 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */
+	{ 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */
+	{ 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */
+	{ 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */
+	{ 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */
+/* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx
+	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+	{ 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */
+	{ 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */
+	{ 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */
+	{ 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */
+	{ 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */
+	{ 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */
+	{ 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+	{ 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */
+/* E
+	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+	{ 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E  */
 	{ 0, },	/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, pci_tbl);
@@ -138,22 +213,115 @@
 };
 
 
+#ifdef CONFIG_SMP
+static char __initdata waitflag;
+
+static void __init intel_init_wait(void *unused)
+{
+	while (waitflag)
+		cpu_relax();
+}
+#endif
+
 static int __init mod_init(void)
 {
 	int err = -ENODEV;
+	unsigned i;
+	struct pci_dev *dev = NULL;
 	void __iomem *mem;
-	u8 hw_status;
+	unsigned long flags;
+	u8 bios_cntl_off, fwh_dec_en1_off;
+	u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff;
+	u8 hw_status, mfc, dvc;
 
-	if (!pci_dev_present(pci_tbl))
+	for (i = 0; !dev && pci_tbl[i].vendor; ++i)
+		dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL);
+
+	if (!dev)
 		goto out; /* Device not found. */
 
+	/* Check for Intel 82802 */
+	if (dev->device < 0x2640) {
+		fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
+		bios_cntl_off = BIOS_CNTL_REG_OLD;
+	} else {
+		fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW;
+		bios_cntl_off = BIOS_CNTL_REG_NEW;
+	}
+
+	pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
+	pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
+
+	mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
+	if (mem == NULL) {
+		pci_dev_put(dev);
+		err = -EBUSY;
+		goto out;
+	}
+
+	/*
+	 * Since the BIOS code/data is going to disappear from its normal
+	 * location with the Read ID command, all activity on the system
+	 * must be stopped until the state is back to normal.
+	 */
+#ifdef CONFIG_SMP
+	set_mb(waitflag, 1);
+	if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) {
+		set_mb(waitflag, 0);
+		pci_dev_put(dev);
+		printk(KERN_ERR PFX "cannot run on all processors\n");
+		err = -EAGAIN;
+		goto err_unmap;
+	}
+#endif
+	local_irq_save(flags);
+
+	if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
+		pci_write_config_byte(dev,
+		                      fwh_dec_en1_off,
+		                      fwh_dec_en1_val | FWH_F8_EN_MASK);
+	if (!(bios_cntl_val &
+	      (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+		pci_write_config_byte(dev,
+		                      bios_cntl_off,
+		                      bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
+
+	writeb(INTEL_FWH_RESET_CMD, mem);
+	writeb(INTEL_FWH_READ_ID_CMD, mem);
+	mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS);
+	dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS);
+	writeb(INTEL_FWH_RESET_CMD, mem);
+
+	if (!(bios_cntl_val &
+	      (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+		pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val);
+	if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
+		pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val);
+
+	local_irq_restore(flags);
+#ifdef CONFIG_SMP
+	/* Tell other CPUs to resume. */
+	set_mb(waitflag, 0);
+#endif
+
+	iounmap(mem);
+	pci_dev_put(dev);
+
+	if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
+	    (dvc != INTEL_FWH_DEVICE_CODE_8M &&
+	     dvc != INTEL_FWH_DEVICE_CODE_4M)) {
+		printk(KERN_ERR PFX "FWH not detected\n");
+		err = -ENODEV;
+		goto out;
+	}
+
 	err = -ENOMEM;
 	mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
 	if (!mem)
 		goto out;
 	intel_rng.priv = (unsigned long)mem;
 
-	/* Check for Intel 82802 */
+	/* Check for Random Number Generator */
 	err = -ENODEV;
 	hw_status = hwstatus_get(mem);
 	if ((hw_status & INTEL_RNG_PRESENT) == 0)
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 8c09997..6b4d82a 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -612,16 +612,6 @@
 #define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
 #define	MINOR2PORT(min)		((min) & 0x3f)
 
-/*
- *	Define a baud rate table that converts termios baud rate selector
- *	into the actual baud rate value. All baud rate calculations are based
- *	on the actual baud rate required.
- */
-static unsigned int	stli_baudrates[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
-};
-
 /*****************************************************************************/
 
 /*
@@ -2747,15 +2737,7 @@
 /*
  *	Start of by setting the baud, char size, parity and stop bit info.
  */
-	pp->baudout = tiosp->c_cflag & CBAUD;
-	if (pp->baudout & CBAUDEX) {
-		pp->baudout &= ~CBAUDEX;
-		if ((pp->baudout < 1) || (pp->baudout > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			pp->baudout += 15;
-	}
-	pp->baudout = stli_baudrates[pp->baudout];
+	pp->baudout = tty_get_baud_rate(portp->tty);
 	if ((tiosp->c_cflag & CBAUD) == B38400) {
 		if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 			pp->baudout = 57600;
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index f875fda..1ecea7d 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -906,7 +906,7 @@
 	lp_class = class_create(THIS_MODULE, "printer");
 	if (IS_ERR(lp_class)) {
 		err = PTR_ERR(lp_class);
-		goto out_devfs;
+		goto out_reg;
 	}
 
 	if (parport_register_driver (&lp_driver)) {
@@ -927,7 +927,7 @@
 
 out_class:
 	class_destroy(lp_class);
-out_devfs:
+out_reg:
 	unregister_chrdev(LP_MAJOR, "lp");
 	return err;
 }
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 4ac70ec..6511012 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -551,7 +551,7 @@
  	return virtr + wrote;
 }
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
 static ssize_t read_port(struct file * file, char __user * buf,
 			 size_t count, loff_t *ppos)
 {
@@ -830,7 +830,7 @@
 	.splice_write	= splice_write_null,
 };
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
 static const struct file_operations port_fops = {
 	.llseek		= memory_lseek,
 	.read		= read_port,
@@ -908,7 +908,7 @@
 		case 3:
 			filp->f_op = &null_fops;
 			break;
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
 		case 4:
 			filp->f_op = &port_fops;
 			break;
@@ -955,7 +955,7 @@
 	{1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
 	{2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
 	{3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
 	{4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
 #endif
 	{5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 84e5a68..ecfaf18 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -188,16 +188,6 @@
 	pc8736x_gpio_shadow[port] = val;
 }
 
-static void pc8736x_gpio_set_high(unsigned index)
-{
-	pc8736x_gpio_set(index, 1);
-}
-
-static void pc8736x_gpio_set_low(unsigned index)
-{
-	pc8736x_gpio_set(index, 0);
-}
-
 static int pc8736x_gpio_current(unsigned minor)
 {
 	int port, bit;
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 579868a..c596a08 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -288,31 +288,34 @@
 static int __init raw_init(void)
 {
 	dev_t dev = MKDEV(RAW_MAJOR, 0);
+	int ret;
 
-	if (register_chrdev_region(dev, MAX_RAW_MINORS, "raw"))
+	ret = register_chrdev_region(dev, MAX_RAW_MINORS, "raw");
+	if (ret)
 		goto error;
 
 	cdev_init(&raw_cdev, &raw_fops);
-	if (cdev_add(&raw_cdev, dev, MAX_RAW_MINORS)) {
+	ret = cdev_add(&raw_cdev, dev, MAX_RAW_MINORS);
+	if (ret) {
 		kobject_put(&raw_cdev.kobj);
-		unregister_chrdev_region(dev, MAX_RAW_MINORS);
-		goto error;
+		goto error_region;
 	}
 
 	raw_class = class_create(THIS_MODULE, "raw");
 	if (IS_ERR(raw_class)) {
 		printk(KERN_ERR "Error creating raw class.\n");
 		cdev_del(&raw_cdev);
-		unregister_chrdev_region(dev, MAX_RAW_MINORS);
-		goto error;
+		ret = PTR_ERR(raw_class);
+		goto error_region;
 	}
 	class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
 	return 0;
 
+error_region:
+	unregister_chrdev_region(dev, MAX_RAW_MINORS);
 error:
-	printk(KERN_ERR "error register raw device\n");
-	return 1;
+	return ret;
 }
 
 static void __exit raw_exit(void)
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index ab6429b..656f8c0 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1262,10 +1262,8 @@
 	 * Once the read clears, read the RTC time (again via ioctl). Easy.
 	 */
 
-	while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
-		barrier();
+	while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100)
 		cpu_relax();
-	}
 
 	/*
 	 * Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
deleted file mode 100644
index 5458ef1..0000000
--- a/drivers/char/s3c2410-rtc.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/* drivers/char/s3c2410_rtc.c
- *
- * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
- *		      http://www.simtec.co.uk/products/SWLINUX/
- *
- * 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.
- *
- * S3C2410 Internal RTC Driver
- *
- *  Changelog:
- *	08-Nov-2004	BJD	Initial creation
- *	12-Nov-2004	BJD	Added periodic IRQ and PM code
- *	22-Nov-2004	BJD	Sign-test on alarm code to check for <0
- *	10-Mar-2005	LCVR	Changed S3C2410_VA_RTC to S3C24XX_VA_RTC
-*/
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
-#include <linux/clk.h>
-
-#include <asm/hardware.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/rtc.h>
-
-#include <asm/mach/time.h>
-
-#include <asm/arch/regs-rtc.h>
-
-/* need this for the RTC_AF definitions */
-#include <linux/mc146818rtc.h>
-
-#undef S3C24XX_VA_RTC
-#define S3C24XX_VA_RTC s3c2410_rtc_base
-
-static struct resource *s3c2410_rtc_mem;
-
-static void __iomem *s3c2410_rtc_base;
-static int s3c2410_rtc_alarmno = NO_IRQ;
-static int s3c2410_rtc_tickno  = NO_IRQ;
-static int s3c2410_rtc_freq    = 1;
-
-static DEFINE_SPINLOCK(s3c2410_rtc_pie_lock);
-
-/* IRQ Handlers */
-
-static irqreturn_t s3c2410_rtc_alarmirq(int irq, void *id, struct pt_regs *r)
-{
-	rtc_update(1, RTC_AF | RTC_IRQF);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t s3c2410_rtc_tickirq(int irq, void *id, struct pt_regs *r)
-{
-	rtc_update(1, RTC_PF | RTC_IRQF);
-	return IRQ_HANDLED;
-}
-
-/* Update control registers */
-static void s3c2410_rtc_setaie(int to)
-{
-	unsigned int tmp;
-
-	pr_debug("%s: aie=%d\n", __FUNCTION__, to);
-
-	tmp = readb(S3C2410_RTCALM);
-
-	if (to)
-		tmp |= S3C2410_RTCALM_ALMEN;
-	else
-		tmp &= ~S3C2410_RTCALM_ALMEN;
-
-
-	writeb(tmp, S3C2410_RTCALM);
-}
-
-static void s3c2410_rtc_setpie(int to)
-{
-	unsigned int tmp;
-
-	pr_debug("%s: pie=%d\n", __FUNCTION__, to);
-
-	spin_lock_irq(&s3c2410_rtc_pie_lock);
-	tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
-
-	if (to)
-		tmp |= S3C2410_TICNT_ENABLE;
-
-	writeb(tmp, S3C2410_TICNT);
-	spin_unlock_irq(&s3c2410_rtc_pie_lock);
-}
-
-static void s3c2410_rtc_setfreq(int freq)
-{
-	unsigned int tmp;
-
-	spin_lock_irq(&s3c2410_rtc_pie_lock);
-	tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
-
-	s3c2410_rtc_freq = freq;
-
-	tmp |= (128 / freq)-1;
-
-	writeb(tmp, S3C2410_TICNT);
-	spin_unlock_irq(&s3c2410_rtc_pie_lock);
-}
-
-/* Time read/write */
-
-static int s3c2410_rtc_gettime(struct rtc_time *rtc_tm)
-{
-	unsigned int have_retried = 0;
-
- retry_get_time:
-	rtc_tm->tm_min  = readb(S3C2410_RTCMIN);
-	rtc_tm->tm_hour = readb(S3C2410_RTCHOUR);
-	rtc_tm->tm_mday = readb(S3C2410_RTCDATE);
-	rtc_tm->tm_mon  = readb(S3C2410_RTCMON);
-	rtc_tm->tm_year = readb(S3C2410_RTCYEAR);
-	rtc_tm->tm_sec  = readb(S3C2410_RTCSEC);
-
-	/* the only way to work out wether the system was mid-update
-	 * when we read it is to check the second counter, and if it
-	 * is zero, then we re-try the entire read
-	 */
-
-	if (rtc_tm->tm_sec == 0 && !have_retried) {
-		have_retried = 1;
-		goto retry_get_time;
-	}
-
-	pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
-		 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
-		 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
-
-	BCD_TO_BIN(rtc_tm->tm_sec);
-	BCD_TO_BIN(rtc_tm->tm_min);
-	BCD_TO_BIN(rtc_tm->tm_hour);
-	BCD_TO_BIN(rtc_tm->tm_mday);
-	BCD_TO_BIN(rtc_tm->tm_mon);
-	BCD_TO_BIN(rtc_tm->tm_year);
-
-	rtc_tm->tm_year += 100;
-	rtc_tm->tm_mon -= 1;
-
-	return 0;
-}
-
-
-static int s3c2410_rtc_settime(struct rtc_time *tm)
-{
-	/* the rtc gets round the y2k problem by just not supporting it */
-
-	if (tm->tm_year < 100)
-		return -EINVAL;
-
-	writeb(BIN2BCD(tm->tm_sec),  S3C2410_RTCSEC);
-	writeb(BIN2BCD(tm->tm_min),  S3C2410_RTCMIN);
-	writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR);
-	writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE);
-	writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON);
-	writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR);
-
-	return 0;
-}
-
-static int s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm)
-{
-	struct rtc_time *alm_tm = &alrm->time;
-	unsigned int alm_en;
-
-	alm_tm->tm_sec  = readb(S3C2410_ALMSEC);
-	alm_tm->tm_min  = readb(S3C2410_ALMMIN);
-	alm_tm->tm_hour = readb(S3C2410_ALMHOUR);
-	alm_tm->tm_mon  = readb(S3C2410_ALMMON);
-	alm_tm->tm_mday = readb(S3C2410_ALMDATE);
-	alm_tm->tm_year = readb(S3C2410_ALMYEAR);
-
-	alm_en = readb(S3C2410_RTCALM);
-
-	pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
-		 alm_en,
-		 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
-		 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
-
-
-	/* decode the alarm enable field */
-
-	if (alm_en & S3C2410_RTCALM_SECEN) {
-		BCD_TO_BIN(alm_tm->tm_sec);
-	} else {
-		alm_tm->tm_sec = 0xff;
-	}
-
-	if (alm_en & S3C2410_RTCALM_MINEN) {
-		BCD_TO_BIN(alm_tm->tm_min);
-	} else {
-		alm_tm->tm_min = 0xff;
-	}
-
-	if (alm_en & S3C2410_RTCALM_HOUREN) {
-		BCD_TO_BIN(alm_tm->tm_hour);
-	} else {
-		alm_tm->tm_hour = 0xff;
-	}
-
-	if (alm_en & S3C2410_RTCALM_DAYEN) {
-		BCD_TO_BIN(alm_tm->tm_mday);
-	} else {
-		alm_tm->tm_mday = 0xff;
-	}
-
-	if (alm_en & S3C2410_RTCALM_MONEN) {
-		BCD_TO_BIN(alm_tm->tm_mon);
-		alm_tm->tm_mon -= 1;
-	} else {
-		alm_tm->tm_mon = 0xff;
-	}
-
-	if (alm_en & S3C2410_RTCALM_YEAREN) {
-		BCD_TO_BIN(alm_tm->tm_year);
-	} else {
-		alm_tm->tm_year = 0xffff;
-	}
-
-	/* todo - set alrm->enabled ? */
-
-	return 0;
-}
-
-static int s3c2410_rtc_setalarm(struct rtc_wkalrm *alrm)
-{
-	struct rtc_time *tm = &alrm->time;
-	unsigned int alrm_en;
-
-	pr_debug("s3c2410_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
-		 alrm->enabled,
-		 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
-		 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
-
-	if (alrm->enabled || 1) {
-		alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
-		writeb(0x00, S3C2410_RTCALM);
-
-		if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
-			alrm_en |= S3C2410_RTCALM_SECEN;
-			writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC);
-		}
-
-		if (tm->tm_min < 60 && tm->tm_min >= 0) {
-			alrm_en |= S3C2410_RTCALM_MINEN;
-			writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN);
-		}
-
-		if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
-			alrm_en |= S3C2410_RTCALM_HOUREN;
-			writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR);
-		}
-
-		pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
-
-		writeb(alrm_en, S3C2410_RTCALM);
-		enable_irq_wake(s3c2410_rtc_alarmno);
-	} else {
-		alrm_en = readb(S3C2410_RTCALM);
-		alrm_en &= ~S3C2410_RTCALM_ALMEN;
-		writeb(alrm_en, S3C2410_RTCALM);
-		disable_irq_wake(s3c2410_rtc_alarmno);
-	}
-
-	return 0;
-}
-
-static int s3c2410_rtc_ioctl(unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case RTC_AIE_OFF:
-	case RTC_AIE_ON:
-		s3c2410_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
-		return 0;
-
-	case RTC_PIE_OFF:
-	case RTC_PIE_ON:
-		s3c2410_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
-		return 0;
-
-	case RTC_IRQP_READ:
-		return put_user(s3c2410_rtc_freq, (unsigned long __user *)arg);
-
-	case RTC_IRQP_SET:
-		if (arg < 1 || arg > 64)
-			return -EINVAL;
-
-		if (!capable(CAP_SYS_RESOURCE))
-			return -EACCES;
-
-		/* check for power of 2 */
-
-		if ((arg & (arg-1)) != 0)
-			return -EINVAL;
-
-		pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
-
-		s3c2410_rtc_setfreq(arg);
-		return 0;
-
-	case RTC_UIE_ON:
-	case RTC_UIE_OFF:
-		return -EINVAL;
-	}
-
-	return -EINVAL;
-}
-
-static int s3c2410_rtc_proc(char *buf)
-{
-	unsigned int rtcalm = readb(S3C2410_RTCALM);
-	unsigned int ticnt = readb (S3C2410_TICNT);
-	char *p = buf;
-
-	p += sprintf(p, "alarm_IRQ\t: %s\n",
-		     (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
-	p += sprintf(p, "periodic_IRQ\t: %s\n",
-		     (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
-	p += sprintf(p, "periodic_freq\t: %d\n", s3c2410_rtc_freq);
-
-	return p - buf;
-}
-
-static int s3c2410_rtc_open(void)
-{
-	int ret;
-
-	ret = request_irq(s3c2410_rtc_alarmno, s3c2410_rtc_alarmirq,
-			  IRQF_DISABLED,  "s3c2410-rtc alarm", NULL);
-
-	if (ret)
-		printk(KERN_ERR "IRQ%d already in use\n", s3c2410_rtc_alarmno);
-
-	ret = request_irq(s3c2410_rtc_tickno, s3c2410_rtc_tickirq,
-			  IRQF_DISABLED,  "s3c2410-rtc tick", NULL);
-
-	if (ret) {
-		printk(KERN_ERR "IRQ%d already in use\n", s3c2410_rtc_tickno);
-		goto tick_err;
-	}
-
-	return ret;
-
- tick_err:
-	free_irq(s3c2410_rtc_alarmno, NULL);
-	return ret;
-}
-
-static void s3c2410_rtc_release(void)
-{
-	/* do not clear AIE here, it may be needed for wake */
-
-	s3c2410_rtc_setpie(0);
-	free_irq(s3c2410_rtc_alarmno, NULL);
-	free_irq(s3c2410_rtc_tickno, NULL);
-}
-
-static struct rtc_ops s3c2410_rtcops = {
-	.owner		= THIS_MODULE,
-	.open		= s3c2410_rtc_open,
-	.release	= s3c2410_rtc_release,
-	.ioctl		= s3c2410_rtc_ioctl,
-	.read_time	= s3c2410_rtc_gettime,
-	.set_time	= s3c2410_rtc_settime,
-	.read_alarm	= s3c2410_rtc_getalarm,
-	.set_alarm	= s3c2410_rtc_setalarm,
-	.proc	        = s3c2410_rtc_proc,
-};
-
-static void s3c2410_rtc_enable(struct platform_device *pdev, int en)
-{
-	unsigned int tmp;
-
-	if (s3c2410_rtc_base == NULL)
-		return;
-
-	if (!en) {
-		tmp = readb(S3C2410_RTCCON);
-		writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON);
-
-		tmp = readb(S3C2410_TICNT);
-		writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT);
-	} else {
-		/* re-enable the device, and check it is ok */
-
-		if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
-			dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
-
-			tmp = readb(S3C2410_RTCCON);
-			writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON);
-		}
-
-		if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
-			dev_info(&pdev->dev, "removing S3C2410_RTCCON_CNTSEL\n");
-
-			tmp = readb(S3C2410_RTCCON);
-			writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON);
-		}
-
-		if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
-			dev_info(&pdev->dev, "removing S3C2410_RTCCON_CLKRST\n");
-
-			tmp = readb(S3C2410_RTCCON);
-			writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON);
-		}
-	}
-}
-
-static int s3c2410_rtc_remove(struct platform_device *dev)
-{
-	unregister_rtc(&s3c2410_rtcops);
-
-	s3c2410_rtc_setpie(0);
-	s3c2410_rtc_setaie(0);
-
-	if (s3c2410_rtc_mem != NULL) {
-		pr_debug("s3c2410_rtc: releasing s3c2410_rtc_mem\n");
-		iounmap(s3c2410_rtc_base);
-		release_resource(s3c2410_rtc_mem);
-		kfree(s3c2410_rtc_mem);
-	}
-
-	return 0;
-}
-
-static int s3c2410_rtc_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	int ret;
-
-	pr_debug("%s: probe=%p\n", __FUNCTION__, pdev);
-
-	/* find the IRQs */
-
-	s3c2410_rtc_tickno = platform_get_irq(pdev, 1);
-	if (s3c2410_rtc_tickno < 0) {
-		dev_err(&pdev->dev, "no irq for rtc tick\n");
-		return -ENOENT;
-	}
-
-	s3c2410_rtc_alarmno = platform_get_irq(pdev, 0);
-	if (s3c2410_rtc_alarmno < 0) {
-		dev_err(&pdev->dev, "no irq for alarm\n");
-		return -ENOENT;
-	}
-
-	pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
-		 s3c2410_rtc_tickno, s3c2410_rtc_alarmno);
-
-	/* get the memory region */
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "failed to get memory region resource\n");
-		return -ENOENT;
-	}
-
-	s3c2410_rtc_mem = request_mem_region(res->start, res->end-res->start+1,
-				     pdev->name);
-
-	if (s3c2410_rtc_mem == NULL) {
-		dev_err(&pdev->dev, "failed to reserve memory region\n");
-		ret = -ENOENT;
-		goto exit_err;
-	}
-
-	s3c2410_rtc_base = ioremap(res->start, res->end - res->start + 1);
-	if (s3c2410_rtc_base == NULL) {
-		dev_err(&pdev->dev, "failed ioremap()\n");
-		ret = -EINVAL;
-		goto exit_err;
-	}
-
-	s3c2410_rtc_mem = res;
-	pr_debug("s3c2410_rtc_base=%p\n", s3c2410_rtc_base);
-
- 	pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
-
-	/* check to see if everything is setup correctly */
-
-	s3c2410_rtc_enable(pdev, 1);
-
- 	pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
-
-	s3c2410_rtc_setfreq(s3c2410_rtc_freq);
-
-	/* register RTC and exit */
-
-	register_rtc(&s3c2410_rtcops);
-	return 0;
-
- exit_err:
-	dev_err(&pdev->dev, "error %d during initialisation\n", ret);
-
-	return ret;
-}
-
-#ifdef CONFIG_PM
-
-/* S3C2410 RTC Power management control */
-
-static struct timespec s3c2410_rtc_delta;
-
-static int ticnt_save;
-
-static int s3c2410_rtc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct rtc_time tm;
-	struct timespec time;
-
-	time.tv_nsec = 0;
-
-	/* save TICNT for anyone using periodic interrupts */
-
-	ticnt_save = readb(S3C2410_TICNT);
-
-	/* calculate time delta for suspend */
-
-	s3c2410_rtc_gettime(&tm);
-	rtc_tm_to_time(&tm, &time.tv_sec);
-	save_time_delta(&s3c2410_rtc_delta, &time);
-	s3c2410_rtc_enable(pdev, 0);
-
-	return 0;
-}
-
-static int s3c2410_rtc_resume(struct platform_device *pdev)
-{
-	struct rtc_time tm;
-	struct timespec time;
-
-	time.tv_nsec = 0;
-
-	s3c2410_rtc_enable(pdev, 1);
-	s3c2410_rtc_gettime(&tm);
-	rtc_tm_to_time(&tm, &time.tv_sec);
-	restore_time_delta(&s3c2410_rtc_delta, &time);
-
-	writeb(ticnt_save, S3C2410_TICNT);
-	return 0;
-}
-#else
-#define s3c2410_rtc_suspend NULL
-#define s3c2410_rtc_resume  NULL
-#endif
-
-static struct platform_driver s3c2410_rtcdrv = {
-	.probe		= s3c2410_rtc_probe,
-	.remove		= s3c2410_rtc_remove,
-	.suspend	= s3c2410_rtc_suspend,
-	.resume		= s3c2410_rtc_resume,
-	.driver		= {
-		.name	= "s3c2410-rtc",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static char __initdata banner[] = "S3C2410 RTC, (c) 2004 Simtec Electronics\n";
-
-static int __init s3c2410_rtc_init(void)
-{
-	printk(banner);
-	return platform_driver_register(&s3c2410_rtcdrv);
-}
-
-static void __exit s3c2410_rtc_exit(void)
-{
-	platform_driver_unregister(&s3c2410_rtcdrv);
-}
-
-module_init(s3c2410_rtc_init);
-module_exit(s3c2410_rtc_exit);
-
-MODULE_DESCRIPTION("S3C24XX RTC Driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index b956c7b..99e5272 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -44,7 +44,7 @@
 	.gpio_change	= scx200_gpio_change,
 	.gpio_current	= scx200_gpio_current
 };
-EXPORT_SYMBOL(scx200_gpio_ops);
+EXPORT_SYMBOL_GPL(scx200_gpio_ops);
 
 static int scx200_gpio_open(struct inode *inode, struct file *file)
 {
@@ -69,7 +69,7 @@
 	.release = scx200_gpio_release,
 };
 
-struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
+static struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
 
 static int __init scx200_gpio_init(void)
 {
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 71093a9..74cff83 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -33,7 +33,7 @@
 
 /* Variables for selection control. */
 /* Use a dynamic buffer, instead of static (Dec 1994) */
-struct vc_data *sel_cons;		/* must not be disallocated */
+struct vc_data *sel_cons;		/* must not be deallocated */
 static volatile int sel_start = -1; 	/* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index a1d303f9..c0ef0f0 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1087,24 +1087,16 @@
 		port->MSVR =  (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
 	spin_unlock_irqrestore(&bp->lock, flags);
 	dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
-	baud = C_BAUD(tty);
+	baud = tty_get_baud_rate(tty);
 
-	if (baud & CBAUDEX) {
-		baud &= ~CBAUDEX;
-		if (baud < 1 || baud > 2)
-			port->tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			baud += 15;
-	}
-	if (baud == 15) {
+	if (baud == 38400) {
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 			baud ++;
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
 			baud += 2;
 	}
 
-
-	if (!baud_table[baud]) {
+	if (!baud) {
 		/* Drop DTR & exit */
 		dprintk (SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
 		if (!SX_CRTSCTS (tty)) {
@@ -1134,7 +1126,7 @@
 		                  "This is an untested option, please be carefull.\n",
 		                  port_No (port), tmp);
 	else
-		tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
+		tmp = (((SX_OSCFREQ + baud/2) / baud +
 		         CD186x_TPC/2) / CD186x_TPC);
 
 	if ((tmp < 0x10) && time_before(again, jiffies)) {
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index ee3ca8f..0ad6cb0 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -208,7 +208,7 @@
 	struct task_struct *p;
 
 	for_each_process(p) {
-		if (p->mm && p->pid != 1)
+		if (p->mm && !is_init(p))
 			/* Not swapper, init nor kernel thread */
 			force_sig(sig, p);
 	}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index bb0d919..33374177 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -129,6 +129,7 @@
 /* Semaphore to protect creating and releasing a tty. This is shared with
    vt.c for deeply disgusting hack reasons */
 DEFINE_MUTEX(tty_mutex);
+EXPORT_SYMBOL(tty_mutex);
 
 #ifdef CONFIG_UNIX98_PTYS
 extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
@@ -160,17 +161,11 @@
  *	been initialized in any way but has been zeroed
  *
  *	Locking: none
- *	FIXME: use kzalloc
  */
 
 static struct tty_struct *alloc_tty_struct(void)
 {
-	struct tty_struct *tty;
-
-	tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
-	if (tty)
-		memset(tty, 0, sizeof(struct tty_struct));
-	return tty;
+	return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
 }
 
 static void tty_buffer_free_all(struct tty_struct *);
@@ -483,10 +478,9 @@
 		tb->used += space;
 		copied += space;
 		chars += space;
-	}
-	/* There is a small chance that we need to split the data over
-	   several buffers. If this is the case we must loop */
-	while (unlikely(size > copied));
+		/* There is a small chance that we need to split the data over
+		   several buffers. If this is the case we must loop */
+	} while (unlikely(size > copied));
 	return copied;
 }
 EXPORT_SYMBOL(tty_insert_flip_string);
@@ -521,10 +515,9 @@
 		copied += space;
 		chars += space;
 		flags += space;
-	}
-	/* There is a small chance that we need to split the data over
-	   several buffers. If this is the case we must loop */
-	while (unlikely(size > copied));
+		/* There is a small chance that we need to split the data over
+		   several buffers. If this is the case we must loop */
+	} while (unlikely(size > copied));
 	return copied;
 }
 EXPORT_SYMBOL(tty_insert_flip_string_flags);
@@ -626,9 +619,9 @@
  
 static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
 {
-	down(&tty->termios_sem);
+	mutex_lock(&tty->termios_mutex);
 	tty->termios->c_line = num;
-	up(&tty->termios_sem);
+	mutex_unlock(&tty->termios_mutex);
 }
 
 /*
@@ -1346,9 +1339,9 @@
 	 */
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
 	{
-		down(&tty->termios_sem);
+		mutex_lock(&tty->termios_mutex);
 		*tty->termios = tty->driver->init_termios;
-		up(&tty->termios_sem);
+		mutex_unlock(&tty->termios_mutex);
 	}
 	
 	/* Defer ldisc switch */
@@ -2072,8 +2065,9 @@
 
 	/* call the tty release_mem routine to clean out this slot */
 release_mem_out:
-	printk(KERN_INFO "init_dev: ldisc open failed, "
-			 "clearing slot %d\n", idx);
+	if (printk_ratelimit())
+		printk(KERN_INFO "init_dev: ldisc open failed, "
+				 "clearing slot %d\n", idx);
 	release_mem(tty, idx);
 	goto end_init;
 }
@@ -2726,6 +2720,8 @@
  *	Locking:
  *		Called functions take tty_ldisc_lock
  *		current->signal->tty check is safe without locks
+ *
+ *	FIXME: may race normal receive processing
  */
 
 static int tiocsti(struct tty_struct *tty, char __user *p)
@@ -2748,18 +2744,21 @@
  *	@tty; tty
  *	@arg: user buffer for result
  *
- *	Copies the kernel idea of the window size into the user buffer. No
- *	locking is done.
+ *	Copies the kernel idea of the window size into the user buffer.
  *
- *	FIXME: Returning random values racing a window size set is wrong
- *	should lock here against that
+ *	Locking: tty->termios_sem is taken to ensure the winsize data
+ *		is consistent.
  */
 
 static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
 {
-	if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
-		return -EFAULT;
-	return 0;
+	int err;
+
+	mutex_lock(&tty->termios_mutex);
+	err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
+	mutex_unlock(&tty->termios_mutex);
+
+	return err ? -EFAULT: 0;
 }
 
 /**
@@ -2772,12 +2771,11 @@
  *	actually has driver level meaning and triggers a VC resize.
  *
  *	Locking:
- *		The console_sem is used to ensure we do not try and resize
- *	the console twice at once.
- *	FIXME: Two racing size sets may leave the console and kernel
- *		parameters disagreeing. Is this exploitable ?
- *	FIXME: Random values racing a window size get is wrong
- *	should lock here against that
+ *		Called function use the console_sem is used to ensure we do
+ *	not try and resize the console twice at once.
+ *		The tty->termios_sem is used to ensure we don't double
+ *	resize and get confused. Lock order - tty->termios.sem before
+ *	console sem
  */
 
 static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
@@ -2787,17 +2785,18 @@
 
 	if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
 		return -EFAULT;
+
+	mutex_lock(&tty->termios_mutex);
 	if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
-		return 0;
+		goto done;
+
 #ifdef CONFIG_VT
 	if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
-		int rc;
-
-		acquire_console_sem();
-		rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
-		release_console_sem();
-		if (rc)
-			return -ENXIO;
+		if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col,
+					tmp_ws.ws_row)) {
+			mutex_unlock(&tty->termios_mutex);
+ 			return -ENXIO;
+		}
 	}
 #endif
 	if (tty->pgrp > 0)
@@ -2806,6 +2805,8 @@
 		kill_pg(real_tty->pgrp, SIGWINCH, 1);
 	tty->winsize = tmp_ws;
 	real_tty->winsize = tmp_ws;
+done:
+	mutex_unlock(&tty->termios_mutex);
 	return 0;
 }
 
@@ -2880,9 +2881,7 @@
  *	Locking:
  *		Takes tasklist lock internally to walk sessions
  *		Takes task_lock() when updating signal->tty
- *
- *	FIXME: tty_mutex is needed to protect signal->tty references.
- *	FIXME: why task_lock on the signal->tty reference ??
+ *		Takes tty_mutex() to protect tty instance
  *
  */
 
@@ -2917,9 +2916,11 @@
 		} else
 			return -EPERM;
 	}
+	mutex_lock(&tty_mutex);
 	task_lock(current);
 	current->signal->tty = tty;
 	task_unlock(current);
+	mutex_unlock(&tty_mutex);
 	current->signal->tty_old_pgrp = 0;
 	tty->session = current->signal->session;
 	tty->pgrp = process_group(current);
@@ -2959,8 +2960,6 @@
  *	permitted where the tty session is our session.
  *
  *	Locking: None
- *
- *	FIXME: current->signal->tty referencing is unsafe.
  */
 
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3039,19 +3038,20 @@
  *	timed break functionality.
  *
  *	Locking:
- *		None
+ *		atomic_write_lock serializes
  *
- *	FIXME:
- *		What if two overlap
  */
 
 static int send_break(struct tty_struct *tty, unsigned int duration)
 {
+	if (mutex_lock_interruptible(&tty->atomic_write_lock))
+		return -EINTR;
 	tty->driver->break_ctl(tty, -1);
 	if (!signal_pending(current)) {
 		msleep_interruptible(duration);
 	}
 	tty->driver->break_ctl(tty, 0);
+	mutex_unlock(&tty->atomic_write_lock);
 	if (signal_pending(current))
 		return -EINTR;
 	return 0;
@@ -3144,6 +3144,8 @@
 	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
 		return -EINVAL;
 
+	/* CHECKME: is this safe as one end closes ? */
+
 	real_tty = tty;
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver->subtype == PTY_TYPE_MASTER)
@@ -3580,7 +3582,7 @@
 	tty_buffer_init(tty);
 	INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
 	init_MUTEX(&tty->buf.pty_sem);
-	init_MUTEX(&tty->termios_sem);
+	mutex_init(&tty->termios_mutex);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
 	INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 4ad47d3..3b6fa7b 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -131,7 +132,7 @@
 
 	/* FIXME: we need to decide on some locking/ordering semantics
 	   for the set_termios notification eventually */
-	down(&tty->termios_sem);
+	mutex_lock(&tty->termios_mutex);
 
 	*tty->termios = *new_termios;
 	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
@@ -176,7 +177,7 @@
 			(ld->set_termios)(tty, &old_termios);
 		tty_ldisc_deref(ld);
 	}
-	up(&tty->termios_sem);
+	mutex_unlock(&tty->termios_mutex);
 }
 
 /**
@@ -284,13 +285,13 @@
 {
 	struct sgttyb tmp;
 
-	down(&tty->termios_sem);
+	mutex_lock(&tty->termios_mutex);
 	tmp.sg_ispeed = 0;
 	tmp.sg_ospeed = 0;
 	tmp.sg_erase = tty->termios->c_cc[VERASE];
 	tmp.sg_kill = tty->termios->c_cc[VKILL];
 	tmp.sg_flags = get_sgflags(tty);
-	up(&tty->termios_sem);
+	mutex_unlock(&tty->termios_mutex);
 	
 	return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
@@ -345,12 +346,12 @@
 	if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
 		return -EFAULT;
 
-	down(&tty->termios_sem);		
+	mutex_lock(&tty->termios_mutex);
 	termios =  *tty->termios;
 	termios.c_cc[VERASE] = tmp.sg_erase;
 	termios.c_cc[VKILL] = tmp.sg_kill;
 	set_sgflags(&termios, tmp.sg_flags);
-	up(&tty->termios_sem);
+	mutex_unlock(&tty->termios_mutex);
 	change_termios(tty, &termios);
 	return 0;
 }
@@ -422,24 +423,28 @@
  *
  *	Send a high priority character to the tty even if stopped
  *
- *	Locking: none
- *
- *	FIXME: overlapping calls with start/stop tty lose state of tty
+ *	Locking: none for xchar method, write ordering for write method.
  */
 
-static void send_prio_char(struct tty_struct *tty, char ch)
+static int send_prio_char(struct tty_struct *tty, char ch)
 {
 	int	was_stopped = tty->stopped;
 
 	if (tty->driver->send_xchar) {
 		tty->driver->send_xchar(tty, ch);
-		return;
+		return 0;
 	}
+
+	if (mutex_lock_interruptible(&tty->atomic_write_lock))
+		return -ERESTARTSYS;
+
 	if (was_stopped)
 		start_tty(tty);
 	tty->driver->write(tty, &ch, 1);
 	if (was_stopped)
 		stop_tty(tty);
+	mutex_unlock(&tty->atomic_write_lock);
+	return 0;
 }
 
 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
@@ -513,11 +518,11 @@
 				break;
 			case TCIOFF:
 				if (STOP_CHAR(tty) != __DISABLED_CHAR)
-					send_prio_char(tty, STOP_CHAR(tty));
+					return send_prio_char(tty, STOP_CHAR(tty));
 				break;
 			case TCION:
 				if (START_CHAR(tty) != __DISABLED_CHAR)
-					send_prio_char(tty, START_CHAR(tty));
+					return send_prio_char(tty, START_CHAR(tty));
 				break;
 			default:
 				return -EINVAL;
@@ -592,11 +597,11 @@
 		case TIOCSSOFTCAR:
 			if (get_user(arg, (unsigned int __user *) arg))
 				return -EFAULT;
-			down(&tty->termios_sem);
+			mutex_lock(&tty->termios_mutex);
 			tty->termios->c_cflag =
 				((tty->termios->c_cflag & ~CLOCAL) |
 				 (arg ? CLOCAL : 0));
-			up(&tty->termios_sem);
+			mutex_unlock(&tty->termios_mutex);
 			return 0;
 		default:
 			return -ENOIOCTLCMD;
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index a9247b5..bd7a98c 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -474,14 +474,15 @@
 
 static struct class *vc_class;
 
-void vcs_make_devfs(struct tty_struct *tty)
+void vcs_make_sysfs(struct tty_struct *tty)
 {
 	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
 			NULL, "vcs%u", tty->index + 1);
 	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
 			NULL, "vcsa%u", tty->index + 1);
 }
-void vcs_remove_devfs(struct tty_struct *tty)
+
+void vcs_remove_sysfs(struct tty_struct *tty)
 {
 	class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
 	class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index da7e66a..fb75da9 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -63,6 +63,13 @@
  *
  * Removed console_lock, enabled interrupts across all console operations
  * 13 March 2001, Andrew Morton
+ *
+ * Fixed UTF-8 mode so alternate charset modes always work according
+ * to control sequences interpreted in do_con_trol function
+ * preserving backward VT100 semigraphics compatibility,
+ * malformed UTF sequences represented as sequences of replacement glyphs,
+ * original codes or '?' as a last resort if replacement glyph is undefined
+ * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
  */
 
 #include <linux/module.h>
@@ -128,8 +135,8 @@
 #define DEFAULT_BELL_PITCH	750
 #define DEFAULT_BELL_DURATION	(HZ/8)
 
-extern void vcs_make_devfs(struct tty_struct *tty);
-extern void vcs_remove_devfs(struct tty_struct *tty);
+extern void vcs_make_sysfs(struct tty_struct *tty);
+extern void vcs_remove_sysfs(struct tty_struct *tty);
 
 extern void console_map_init(void);
 #ifdef CONFIG_PROM_CONSOLE
@@ -730,7 +737,8 @@
 	    visual_init(vc, currcons, 1);
 	    if (!*vc->vc_uni_pagedir_loc)
 		con_set_default_unimap(vc);
-	    vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+	    if (!vc->vc_kmalloced)
+		vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
 	    if (!vc->vc_screenbuf) {
 		kfree(vc);
 		vc_cons[currcons].d = NULL;
@@ -878,8 +886,17 @@
 	return err;
 }
 
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+{
+	int rc;
 
-void vc_disallocate(unsigned int currcons)
+	acquire_console_sem();
+	rc = vc_resize(vc, cols, lines);
+	release_console_sem();
+	return rc;
+}
+
+void vc_deallocate(unsigned int currcons)
 {
 	WARN_CONSOLE_UNLOCKED();
 
@@ -2005,17 +2022,23 @@
 		/* Do no translation at all in control states */
 		if (vc->vc_state != ESnormal) {
 			tc = c;
-		} else if (vc->vc_utf) {
+		} else if (vc->vc_utf && !vc->vc_disp_ctrl) {
 		    /* Combine UTF-8 into Unicode */
-		    /* Incomplete characters silently ignored */
+		    /* Malformed sequences as sequences of replacement glyphs */
+rescan_last_byte:
 		    if(c > 0x7f) {
-			if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) {
-				vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
-				vc->vc_utf_count--;
-				if (vc->vc_utf_count == 0)
-				    tc = c = vc->vc_utf_char;
-				else continue;
+			if (vc->vc_utf_count) {
+			       if ((c & 0xc0) == 0x80) {
+				       vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
+       				       if (--vc->vc_utf_count) {
+					       vc->vc_npar++;
+				   	       continue;
+       				       }
+				       tc = c = vc->vc_utf_char;
+			       } else
+				       goto replacement_glyph;
 			} else {
+				vc->vc_npar = 0;
 				if ((c & 0xe0) == 0xc0) {
 				    vc->vc_utf_count = 1;
 				    vc->vc_utf_char = (c & 0x1f);
@@ -2032,14 +2055,15 @@
 				    vc->vc_utf_count = 5;
 				    vc->vc_utf_char = (c & 0x01);
 				} else
-				    vc->vc_utf_count = 0;
+	    			    goto replacement_glyph;
 				continue;
 			      }
 		    } else {
+		      if (vc->vc_utf_count)
+	  		      goto replacement_glyph;
 		      tc = c;
-		      vc->vc_utf_count = 0;
 		    }
-		} else {	/* no utf */
+		} else {	/* no utf or alternate charset mode */
 		  tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
 		}
 
@@ -2054,31 +2078,33 @@
                  * direct-to-font zone in UTF-8 mode.
                  */
                 ok = tc && (c >= 32 ||
-			    (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS
-						: CTRL_ACTION) >> c) & 1)))
+			    !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
+				  vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
 			&& (c != 127 || vc->vc_disp_ctrl)
 			&& (c != 128+27);
 
 		if (vc->vc_state == ESnormal && ok) {
 			/* Now try to find out how to display it */
 			tc = conv_uni_to_pc(vc, tc);
-			if ( tc == -4 ) {
+			if (tc & ~charmask) {
+				if ( tc == -4 ) {
                                 /* If we got -4 (not found) then see if we have
                                    defined a replacement character (U+FFFD) */
-                                tc = conv_uni_to_pc(vc, 0xfffd);
+replacement_glyph:
+                                	tc = conv_uni_to_pc(vc, 0xfffd);
+					if (!(tc & ~charmask))
+						goto display_glyph;
+                        	} else if ( tc != -3 )
+                                	continue; /* nothing to display */
+                                /* no hash table or no replacement --
+				 * hope for the best */
+				if ( c & ~charmask )
+					tc = '?';
+				else
+					tc = c;
+			}
 
-				/* One reason for the -4 can be that we just
-				   did a clear_unimap();
-				   try at least to show something. */
-				if (tc == -4)
-				     tc = c;
-                        } else if ( tc == -3 ) {
-                                /* Bad hash table -- hope for the best */
-                                tc = c;
-                        }
-			if (tc & ~charmask)
-                                continue; /* Conversion failed */
-
+display_glyph:
 			if (vc->vc_need_wrap || vc->vc_decim)
 				FLUSH
 			if (vc->vc_need_wrap) {
@@ -2102,6 +2128,15 @@
 				vc->vc_x++;
 				draw_to = (vc->vc_pos += 2);
 			}
+			if (vc->vc_utf_count) {
+				if (vc->vc_npar) {
+					vc->vc_npar--;
+					goto display_glyph;
+				}
+				vc->vc_utf_count = 0;
+				c = orig;
+				goto rescan_last_byte;
+			}
 			continue;
 		}
 		FLUSH
@@ -2498,7 +2533,7 @@
 				tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
 			}
 			release_console_sem();
-			vcs_make_devfs(tty);
+			vcs_make_sysfs(tty);
 			return ret;
 		}
 	}
@@ -2511,7 +2546,7 @@
  * and taking a ref against the tty while we're in the process of forgetting
  * about it and cleaning things up.
  *
- * This is because vcs_remove_devfs() can sleep and will drop the BKL.
+ * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
  */
 static void con_close(struct tty_struct *tty, struct file *filp)
 {
@@ -2524,7 +2559,7 @@
 			vc->vc_tty = NULL;
 		tty->driver_data = NULL;
 		release_console_sem();
-		vcs_remove_devfs(tty);
+		vcs_remove_sysfs(tty);
 		mutex_unlock(&tty_mutex);
 		/*
 		 * tty_mutex is released, but we still hold BKL, so there is
@@ -3765,6 +3800,7 @@
 EXPORT_SYMBOL(update_region);
 EXPORT_SYMBOL(redraw_screen);
 EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(vc_lock_resize);
 EXPORT_SYMBOL(fg_console);
 EXPORT_SYMBOL(console_blank_hook);
 EXPORT_SYMBOL(console_blanked);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index a5628a8..a53e382 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -96,7 +96,7 @@
 		if (!perm)
 			return -EPERM;
 		if (!i && v == K_NOSUCHMAP) {
-			/* disallocate map */
+			/* deallocate map */
 			key_map = key_maps[s];
 			if (s && key_map) {
 			    key_maps[s] = NULL;
@@ -819,20 +819,20 @@
 		if (arg > MAX_NR_CONSOLES)
 			return -ENXIO;
 		if (arg == 0) {
-		    /* disallocate all unused consoles, but leave 0 */
+		    /* deallocate all unused consoles, but leave 0 */
 			acquire_console_sem();
 			for (i=1; i<MAX_NR_CONSOLES; i++)
 				if (! VT_BUSY(i))
-					vc_disallocate(i);
+					vc_deallocate(i);
 			release_console_sem();
 		} else {
-			/* disallocate a single console, if possible */
+			/* deallocate a single console, if possible */
 			arg--;
 			if (VT_BUSY(arg))
 				return -EBUSY;
 			if (arg) {			      /* leave 0 */
 				acquire_console_sem();
-				vc_disallocate(arg);
+				vc_deallocate(arg);
 				release_console_sem();
 			}
 		}
@@ -847,11 +847,8 @@
 		if (get_user(ll, &vtsizes->v_rows) ||
 		    get_user(cc, &vtsizes->v_cols))
 			return -EFAULT;
-		for (i = 0; i < MAX_NR_CONSOLES; i++) {
-			acquire_console_sem();
-			vc_resize(vc_cons[i].d, cc, ll);
-			release_console_sem();
-		}
+		for (i = 0; i < MAX_NR_CONSOLES; i++)
+			vc_lock_resize(vc_cons[i].d, cc, ll);
 		return 0;
 	}
 
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index f114d7b..77ab7e0 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -165,6 +165,13 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ep93xx_wdt.
 
+config OMAP_WATCHDOG
+	tristate "OMAP Watchdog"
+	depends on WATCHDOG && (ARCH_OMAP16XX || ARCH_OMAP24XX)
+	help
+	  Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog.  Say 'Y' here to
+	  enable the OMAP1610/OMAP1710 watchdog timer.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 6ab77b6..5099f8b 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -24,6 +24,7 @@
 
 # ARM Architecture
 obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
+obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
new file mode 100644
index 0000000..8f90b90
--- /dev/null
+++ b/drivers/char/watchdog/omap_wdt.c
@@ -0,0 +1,391 @@
+/*
+ * linux/drivers/char/watchdog/omap_wdt.c
+ *
+ * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
+ *
+ * Author: MontaVista Software, Inc.
+ *	 <gdavis@mvista.com> or <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * History:
+ *
+ * 20030527: George G. Davis <gdavis@mvista.com>
+ *	Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
+ *	(c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *	Based on SoftDog driver by Alan Cox <alan@redhat.com>
+ *
+ * Copyright (c) 2004 Texas Instruments.
+ *	1. Modified to support OMAP1610 32-KHz watchdog timer
+ *	2. Ported to 2.6 kernel
+ *
+ * Copyright (c) 2005 David Brownell
+ *	Use the driver model and standard identifiers; handle bigger timeouts.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/moduleparam.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+
+#include <asm/arch/prcm.h>
+
+#include "omap_wdt.h"
+
+static unsigned timer_margin;
+module_param(timer_margin, uint, 0);
+MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
+
+static int omap_wdt_users;
+static struct clk *armwdt_ck = NULL;
+static struct clk *mpu_wdt_ick = NULL;
+static struct clk *mpu_wdt_fck = NULL;
+
+static unsigned int wdt_trgr_pattern = 0x1234;
+
+static void omap_wdt_ping(void)
+{
+	/* wait for posted write to complete */
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+		cpu_relax();
+	wdt_trgr_pattern = ~wdt_trgr_pattern;
+	omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
+	/* wait for posted write to complete */
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+		cpu_relax();
+	/* reloaded WCRR from WLDR */
+}
+
+static void omap_wdt_enable(void)
+{
+	/* Sequence to enable the watchdog */
+	omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+		cpu_relax();
+	omap_writel(0x4444, OMAP_WATCHDOG_SPR);
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+		cpu_relax();
+}
+
+static void omap_wdt_disable(void)
+{
+	/* sequence required to disable watchdog */
+	omap_writel(0xAAAA, OMAP_WATCHDOG_SPR);	/* TIMER_MODE */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+		cpu_relax();
+	omap_writel(0x5555, OMAP_WATCHDOG_SPR);	/* TIMER_MODE */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+		cpu_relax();
+}
+
+static void omap_wdt_adjust_timeout(unsigned new_timeout)
+{
+	if (new_timeout < TIMER_MARGIN_MIN)
+		new_timeout = TIMER_MARGIN_DEFAULT;
+	if (new_timeout > TIMER_MARGIN_MAX)
+		new_timeout = TIMER_MARGIN_MAX;
+	timer_margin = new_timeout;
+}
+
+static void omap_wdt_set_timeout(void)
+{
+	u32 pre_margin = GET_WLDR_VAL(timer_margin);
+
+	/* just count up at 32 KHz */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+		cpu_relax();
+	omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+		cpu_relax();
+}
+
+/*
+ *	Allow only one task to hold it open
+ */
+
+static int omap_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
+		return -EBUSY;
+
+	if (cpu_is_omap16xx())
+		clk_enable(armwdt_ck);	/* Enable the clock */
+
+	if (cpu_is_omap24xx()) {
+		clk_enable(mpu_wdt_ick);    /* Enable the interface clock */
+		clk_enable(mpu_wdt_fck);    /* Enable the functional clock */
+	}
+
+	/* initialize prescaler */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+		cpu_relax();
+	omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+		cpu_relax();
+
+	omap_wdt_set_timeout();
+	omap_wdt_enable();
+	return 0;
+}
+
+static int omap_wdt_release(struct inode *inode, struct file *file)
+{
+	/*
+	 *      Shut off the timer unless NOWAYOUT is defined.
+	 */
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
+	omap_wdt_disable();
+
+	if (cpu_is_omap16xx()) {
+		clk_disable(armwdt_ck);	/* Disable the clock */
+		clk_put(armwdt_ck);
+		armwdt_ck = NULL;
+	}
+
+	if (cpu_is_omap24xx()) {
+		clk_disable(mpu_wdt_ick);	/* Disable the clock */
+		clk_disable(mpu_wdt_fck);	/* Disable the clock */
+		clk_put(mpu_wdt_ick);
+		clk_put(mpu_wdt_fck);
+		mpu_wdt_ick = NULL;
+		mpu_wdt_fck = NULL;
+	}
+#else
+	printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
+#endif
+	omap_wdt_users = 0;
+	return 0;
+}
+
+static ssize_t
+omap_wdt_write(struct file *file, const char __user *data,
+		size_t len, loff_t *ppos)
+{
+	/* Refresh LOAD_TIME. */
+	if (len)
+		omap_wdt_ping();
+	return len;
+}
+
+static int
+omap_wdt_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg)
+{
+	int new_margin;
+	static struct watchdog_info ident = {
+		.identity = "OMAP Watchdog",
+		.options = WDIOF_SETTIMEOUT,
+		.firmware_version = 0,
+	};
+
+	switch (cmd) {
+	default:
+		return -ENOIOCTLCMD;
+	case WDIOC_GETSUPPORT:
+		return copy_to_user((struct watchdog_info __user *)arg, &ident,
+				sizeof(ident));
+	case WDIOC_GETSTATUS:
+		return put_user(0, (int __user *)arg);
+	case WDIOC_GETBOOTSTATUS:
+		if (cpu_is_omap16xx())
+			return put_user(omap_readw(ARM_SYSST),
+					(int __user *)arg);
+		if (cpu_is_omap24xx())
+			return put_user(omap_prcm_get_reset_sources(),
+					(int __user *)arg);
+	case WDIOC_KEEPALIVE:
+		omap_wdt_ping();
+		return 0;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int __user *)arg))
+			return -EFAULT;
+		omap_wdt_adjust_timeout(new_margin);
+
+		omap_wdt_disable();
+		omap_wdt_set_timeout();
+		omap_wdt_enable();
+
+		omap_wdt_ping();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		return put_user(timer_margin, (int __user *)arg);
+	}
+}
+
+static struct file_operations omap_wdt_fops = {
+	.owner = THIS_MODULE,
+	.write = omap_wdt_write,
+	.ioctl = omap_wdt_ioctl,
+	.open = omap_wdt_open,
+	.release = omap_wdt_release,
+};
+
+static struct miscdevice omap_wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &omap_wdt_fops
+};
+
+static int __init omap_wdt_probe(struct platform_device *pdev)
+{
+	struct resource *res, *mem;
+	int ret;
+
+	/* reserve static register mappings */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOENT;
+
+	mem = request_mem_region(res->start, res->end - res->start + 1,
+				 pdev->name);
+	if (mem == NULL)
+		return -EBUSY;
+
+	platform_set_drvdata(pdev, mem);
+
+	omap_wdt_users = 0;
+
+	if (cpu_is_omap16xx()) {
+		armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
+		if (IS_ERR(armwdt_ck)) {
+			ret = PTR_ERR(armwdt_ck);
+			armwdt_ck = NULL;
+			goto fail;
+		}
+	}
+
+	if (cpu_is_omap24xx()) {
+		mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
+		if (IS_ERR(mpu_wdt_ick)) {
+			ret = PTR_ERR(mpu_wdt_ick);
+			mpu_wdt_ick = NULL;
+			goto fail;
+		}
+		mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
+		if (IS_ERR(mpu_wdt_fck)) {
+			ret = PTR_ERR(mpu_wdt_fck);
+			mpu_wdt_fck = NULL;
+			goto fail;
+		}
+	}
+
+	omap_wdt_disable();
+	omap_wdt_adjust_timeout(timer_margin);
+
+	omap_wdt_miscdev.dev = &pdev->dev;
+	ret = misc_register(&omap_wdt_miscdev);
+	if (ret)
+		goto fail;
+
+	pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
+
+	/* autogate OCP interface clock */
+	omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
+	return 0;
+
+fail:
+	if (armwdt_ck)
+		clk_put(armwdt_ck);
+	if (mpu_wdt_ick)
+		clk_put(mpu_wdt_ick);
+	if (mpu_wdt_fck)
+		clk_put(mpu_wdt_fck);
+	release_resource(mem);
+	return ret;
+}
+
+static void omap_wdt_shutdown(struct platform_device *pdev)
+{
+	omap_wdt_disable();
+}
+
+static int omap_wdt_remove(struct platform_device *pdev)
+{
+	struct resource *mem = platform_get_drvdata(pdev);
+	misc_deregister(&omap_wdt_miscdev);
+	release_resource(mem);
+	if (armwdt_ck)
+		clk_put(armwdt_ck);
+	if (mpu_wdt_ick)
+		clk_put(mpu_wdt_ick);
+	if (mpu_wdt_fck)
+		clk_put(mpu_wdt_fck);
+	return 0;
+}
+
+#ifdef	CONFIG_PM
+
+/* REVISIT ... not clear this is the best way to handle system suspend; and
+ * it's very inappropriate for selective device suspend (e.g. suspending this
+ * through sysfs rather than by stopping the watchdog daemon).  Also, this
+ * may not play well enough with NOWAYOUT...
+ */
+
+static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (omap_wdt_users)
+		omap_wdt_disable();
+	return 0;
+}
+
+static int omap_wdt_resume(struct platform_device *pdev)
+{
+	if (omap_wdt_users) {
+		omap_wdt_enable();
+		omap_wdt_ping();
+	}
+	return 0;
+}
+
+#else
+#define	omap_wdt_suspend	NULL
+#define	omap_wdt_resume		NULL
+#endif
+
+static struct platform_driver omap_wdt_driver = {
+	.probe		= omap_wdt_probe,
+	.remove		= omap_wdt_remove,
+	.shutdown	= omap_wdt_shutdown,
+	.suspend	= omap_wdt_suspend,
+	.resume		= omap_wdt_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "omap_wdt",
+	},
+};
+
+static int __init omap_wdt_init(void)
+{
+	return platform_driver_register(&omap_wdt_driver);
+}
+
+static void __exit omap_wdt_exit(void)
+{
+	platform_driver_unregister(&omap_wdt_driver);
+}
+
+module_init(omap_wdt_init);
+module_exit(omap_wdt_exit);
+
+MODULE_AUTHOR("George G. Davis");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/omap_wdt.h b/drivers/char/watchdog/omap_wdt.h
new file mode 100644
index 0000000..52a532a5
--- /dev/null
+++ b/drivers/char/watchdog/omap_wdt.h
@@ -0,0 +1,64 @@
+/*
+ *  linux/drivers/char/watchdog/omap_wdt.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      OMAP Watchdog timer register definitions
+ *
+ *  Copyright (C) 2004 Texas Instruments.
+ *
+ *  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.
+ */
+
+#ifndef _OMAP_WATCHDOG_H
+#define _OMAP_WATCHDOG_H
+
+#define OMAP1610_WATCHDOG_BASE		0xfffeb000
+#define OMAP2420_WATCHDOG_BASE		0x48022000	/*WDT Timer 2 */
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP_WATCHDOG_BASE 		OMAP2420_WATCHDOG_BASE
+#else
+#define OMAP_WATCHDOG_BASE 		OMAP1610_WATCHDOG_BASE
+#define RM_RSTST_WKUP			0
+#endif
+
+#define OMAP_WATCHDOG_REV		(OMAP_WATCHDOG_BASE + 0x00)
+#define OMAP_WATCHDOG_SYS_CONFIG	(OMAP_WATCHDOG_BASE + 0x10)
+#define OMAP_WATCHDOG_STATUS		(OMAP_WATCHDOG_BASE + 0x14)
+#define OMAP_WATCHDOG_CNTRL		(OMAP_WATCHDOG_BASE + 0x24)
+#define OMAP_WATCHDOG_CRR		(OMAP_WATCHDOG_BASE + 0x28)
+#define OMAP_WATCHDOG_LDR		(OMAP_WATCHDOG_BASE + 0x2c)
+#define OMAP_WATCHDOG_TGR		(OMAP_WATCHDOG_BASE + 0x30)
+#define OMAP_WATCHDOG_WPS		(OMAP_WATCHDOG_BASE + 0x34)
+#define OMAP_WATCHDOG_SPR		(OMAP_WATCHDOG_BASE + 0x48)
+
+/* Using the prescaler, the OMAP watchdog could go for many
+ * months before firing.  These limits work without scaling,
+ * with the 60 second default assumed by most tools and docs.
+ */
+#define TIMER_MARGIN_MAX    	(24 * 60 * 60)	/* 1 day */
+#define TIMER_MARGIN_DEFAULT	60	/* 60 secs */
+#define TIMER_MARGIN_MIN	1
+
+#define PTV			0	/* prescale */
+#define GET_WLDR_VAL(secs)	(0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
+
+#endif				/* _OMAP_WATCHDOG_H */
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index b9e3886..b8b596d 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -123,6 +123,26 @@
 		dev->type = *d++ & 0x7f;
 		dev->name = dmi_string(dm, *d);
 		dev->device_data = NULL;
+		list_add(&dev->list, &dmi_devices);
+	}
+}
+
+static void __init dmi_save_oem_strings_devices(struct dmi_header *dm)
+{
+	int i, count = *(u8 *)(dm + 1);
+	struct dmi_device *dev;
+
+	for (i = 1; i <= count; i++) {
+		dev = dmi_alloc(sizeof(*dev));
+		if (!dev) {
+			printk(KERN_ERR
+			   "dmi_save_oem_strings_devices: out of memory.\n");
+			break;
+		}
+
+		dev->type = DMI_DEV_TYPE_OEM_STRING;
+		dev->name = dmi_string(dm, i);
+		dev->device_data = NULL;
 
 		list_add(&dev->list, &dmi_devices);
 	}
@@ -181,6 +201,9 @@
 	case 10:	/* Onboard Devices Information */
 		dmi_save_devices(dm);
 		break;
+	case 11:	/* OEM Strings */
+		dmi_save_oem_strings_devices(dm);
+		break;
 	case 38:	/* IPMI Device Information */
 		dmi_save_ipmi_device(dm);
 	}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 0e31a0c..9b88b25 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -53,7 +53,7 @@
 
 config SENSORS_ADM1025
 	tristate "Analog Devices ADM1025 and compatibles"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for Analog Devices ADM1025
@@ -94,6 +94,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm9240.
 
+config SENSORS_K8TEMP
+	tristate "AMD K8 processor 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.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called k8temp.
+
 config SENSORS_ASB100
 	tristate "Asus ASB100 Bach"
 	depends on HWMON && I2C && EXPERIMENTAL
@@ -121,7 +131,7 @@
 
 config SENSORS_DS1621
 	tristate "Dallas Semiconductor DS1621 and DS1625"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for Dallas Semiconductor
 	  DS1621 and DS1625 sensor chips.
@@ -141,7 +151,7 @@
 
 config SENSORS_FSCHER
 	tristate "FSC Hermes"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for Fujitsu Siemens
 	  Computers Hermes sensor chips.
@@ -151,7 +161,7 @@
 
 config SENSORS_FSCPOS
 	tristate "FSC Poseidon"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for Fujitsu Siemens
 	  Computers Poseidon sensor chips.
@@ -171,7 +181,7 @@
 
 config SENSORS_GL520SM
 	tristate "Genesys Logic GL520SM"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for Genesys Logic GL520SM
@@ -186,15 +196,15 @@
 	select I2C_ISA
 	select HWMON_VID
 	help
-	  If you say yes here you get support for ITE IT87xx sensor chips
-	  and clones: SiS960.
+	  If you say yes here you get support for ITE IT8705F, IT8712F,
+	  IT8716F and IT8718F sensor chips, and the SiS960 clone.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called it87.
 
 config SENSORS_LM63
 	tristate "National Semiconductor LM63"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for the National Semiconductor
 	  LM63 remote diode digital temperature sensor with integrated fan
@@ -231,7 +241,7 @@
 
 config SENSORS_LM77
 	tristate "National Semiconductor LM77"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for National Semiconductor LM77
 	  sensor chips.
@@ -241,7 +251,7 @@
 
 config SENSORS_LM78
 	tristate "National Semiconductor LM78 and compatibles"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	select I2C_ISA
 	select HWMON_VID
 	help
@@ -284,7 +294,7 @@
 
 config SENSORS_LM87
 	tristate "National Semiconductor LM87"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for National Semiconductor LM87
@@ -309,7 +319,7 @@
 
 config SENSORS_LM92
 	tristate "National Semiconductor LM92 and compatibles"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for National Semiconductor LM92
 	  and Maxim MAX6635 sensor chips.
@@ -319,7 +329,7 @@
 
 config SENSORS_MAX1619
 	tristate "Maxim MAX1619 sensor chip"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for MAX1619 sensor chip.
 
@@ -354,7 +364,7 @@
 
 config SENSORS_SMSC47M1
 	tristate "SMSC LPC47M10x and compatibles"
-	depends on HWMON && I2C && EXPERIMENTAL
+	depends on HWMON && I2C
 	select I2C_ISA
 	help
 	  If you say yes here you get support for the integrated fan
@@ -407,8 +417,19 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called via686a.
 
+config SENSORS_VT1211
+	tristate "VIA VT1211"
+	depends on HWMON && EXPERIMENTAL
+	select HWMON_VID
+	help
+	  If you say yes here then you get support for hardware monitoring
+	  features of the VIA VT1211 Super-I/O chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called vt1211.
+
 config SENSORS_VT8231
-	tristate "VT8231"
+	tristate "VIA VT8231"
 	depends on HWMON && I2C && PCI && EXPERIMENTAL
 	select HWMON_VID
 	select I2C_ISA
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3141584..af01cc6 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_SENSORS_GL520SM)	+= gl520sm.o
 obj-$(CONFIG_SENSORS_HDAPS)	+= hdaps.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
+obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
 obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
 obj-$(CONFIG_SENSORS_LM75)	+= lm75.o
@@ -45,6 +46,7 @@
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
+obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
 obj-$(CONFIG_SENSORS_W83627EHF)	+= w83627ehf.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 35ad1b0..e5cb0fd 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -1354,13 +1354,39 @@
 		return NULL;
 }
 
+#ifdef CONFIG_PM
+static int abituguru_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct abituguru_data *data = platform_get_drvdata(pdev);
+	/* make sure all communications with the uguru are done and no new
+	   ones are started */
+	mutex_lock(&data->update_lock);
+	return 0;
+}
+
+static int abituguru_resume(struct platform_device *pdev)
+{
+	struct abituguru_data *data = platform_get_drvdata(pdev);
+	/* See if the uGuru is still ready */
+	if (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT)
+		data->uguru_ready = 0;
+	mutex_unlock(&data->update_lock);
+	return 0;
+}
+#else
+#define abituguru_suspend	NULL
+#define abituguru_resume	NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver abituguru_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= ABIT_UGURU_NAME,
 	},
-	.probe	= abituguru_probe,
-	.remove	= __devexit_p(abituguru_remove),
+	.probe		= abituguru_probe,
+	.remove		= __devexit_p(abituguru_remove),
+	.suspend	= abituguru_suspend,
+	.resume		= abituguru_resume,
 };
 
 static int __init abituguru_detect(void)
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 2b6e74d..c466329 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -190,6 +190,21 @@
 	return i2c_probe(adapter, &addr_data, adm1021_detect);
 }
 
+static struct attribute *adm1021_attributes[] = {
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp2_min.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group adm1021_group = {
+	.attrs = adm1021_attributes,
+};
+
 static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i;
@@ -287,22 +302,19 @@
 		adm1021_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1021_group)))
+		goto error2;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto error2;
+		goto error3;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
 	return 0;
 
+error3:
+	sysfs_remove_group(&new_client->dev.kobj, &adm1021_group);
 error2:
 	i2c_detach_client(new_client);
 error1:
@@ -326,6 +338,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &adm1021_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index a4c859c..8c56288 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -315,6 +315,49 @@
 	return i2c_probe(adapter, &addr_data, adm1025_detect);
 }
 
+static struct attribute *adm1025_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in5_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in5_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_in5_max.attr,
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp2_min.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	NULL
+};
+
+static const struct attribute_group adm1025_group = {
+	.attrs = adm1025_attributes,
+};
+
+static struct attribute *adm1025_attributes_opt[] = {
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+	NULL
+};
+
+static const struct attribute_group adm1025_group_opt = {
+	.attrs = adm1025_attributes_opt,
+};
+
 /*
  * The following function does more than just detection. If detection
  * succeeds, it also registers the new chip.
@@ -415,46 +458,31 @@
 	adm1025_init_client(new_client);
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1025_group)))
 		goto exit_detach;
-	}
-
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in5_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in5_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in5_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-	device_create_file(&new_client->dev, &dev_attr_vrm);
 
 	/* Pin 11 is either in4 (+12V) or VID4 */
 	if (!(config & 0x20)) {
-		device_create_file(&new_client->dev, &dev_attr_in4_input);
-		device_create_file(&new_client->dev, &dev_attr_in4_min);
-		device_create_file(&new_client->dev, &dev_attr_in4_max);
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_in4_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in4_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in4_max)))
+			goto exit_remove;
+	}
+
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove;
 	}
 
 	return 0;
 
+exit_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &adm1025_group);
+	sysfs_remove_group(&new_client->dev.kobj, &adm1025_group_opt);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -511,6 +539,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &adm1025_group);
+	sysfs_remove_group(&client->dev.kobj, &adm1025_group_opt);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 6d4f8b8..b4618b2 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -323,15 +323,6 @@
 	return i2c_probe(adapter, &addr_data, adm1026_detect);
 }
 
-static int adm1026_detach_client(struct i2c_client *client)
-{
-	struct adm1026_data *data = i2c_get_clientdata(client);
-	hwmon_device_unregister(data->class_dev);
-	i2c_detach_client(client);
-	kfree(data);
-	return 0;
-}
-
 static int adm1026_read_value(struct i2c_client *client, u8 reg)
 {
 	int res;
@@ -1450,6 +1441,135 @@
 static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
 static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
 
+static struct attribute *adm1026_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in7_max.dev_attr.attr,
+	&sensor_dev_attr_in7_min.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in8_max.dev_attr.attr,
+	&sensor_dev_attr_in8_min.dev_attr.attr,
+	&sensor_dev_attr_in9_input.dev_attr.attr,
+	&sensor_dev_attr_in9_max.dev_attr.attr,
+	&sensor_dev_attr_in9_min.dev_attr.attr,
+	&sensor_dev_attr_in10_input.dev_attr.attr,
+	&sensor_dev_attr_in10_max.dev_attr.attr,
+	&sensor_dev_attr_in10_min.dev_attr.attr,
+	&sensor_dev_attr_in11_input.dev_attr.attr,
+	&sensor_dev_attr_in11_max.dev_attr.attr,
+	&sensor_dev_attr_in11_min.dev_attr.attr,
+	&sensor_dev_attr_in12_input.dev_attr.attr,
+	&sensor_dev_attr_in12_max.dev_attr.attr,
+	&sensor_dev_attr_in12_min.dev_attr.attr,
+	&sensor_dev_attr_in13_input.dev_attr.attr,
+	&sensor_dev_attr_in13_max.dev_attr.attr,
+	&sensor_dev_attr_in13_min.dev_attr.attr,
+	&sensor_dev_attr_in14_input.dev_attr.attr,
+	&sensor_dev_attr_in14_max.dev_attr.attr,
+	&sensor_dev_attr_in14_min.dev_attr.attr,
+	&sensor_dev_attr_in15_input.dev_attr.attr,
+	&sensor_dev_attr_in15_max.dev_attr.attr,
+	&sensor_dev_attr_in15_min.dev_attr.attr,
+	&sensor_dev_attr_in16_input.dev_attr.attr,
+	&sensor_dev_attr_in16_max.dev_attr.attr,
+	&sensor_dev_attr_in16_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_div.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_div.dev_attr.attr,
+	&sensor_dev_attr_fan4_min.dev_attr.attr,
+	&sensor_dev_attr_fan5_input.dev_attr.attr,
+	&sensor_dev_attr_fan5_div.dev_attr.attr,
+	&sensor_dev_attr_fan5_min.dev_attr.attr,
+	&sensor_dev_attr_fan6_input.dev_attr.attr,
+	&sensor_dev_attr_fan6_div.dev_attr.attr,
+	&sensor_dev_attr_fan6_min.dev_attr.attr,
+	&sensor_dev_attr_fan7_input.dev_attr.attr,
+	&sensor_dev_attr_fan7_div.dev_attr.attr,
+	&sensor_dev_attr_fan7_min.dev_attr.attr,
+	&sensor_dev_attr_fan8_input.dev_attr.attr,
+	&sensor_dev_attr_fan8_div.dev_attr.attr,
+	&sensor_dev_attr_fan8_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_offset.dev_attr.attr,
+	&sensor_dev_attr_temp2_offset.dev_attr.attr,
+	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&dev_attr_temp1_crit_enable.attr,
+	&dev_attr_temp2_crit_enable.attr,
+	&dev_attr_temp3_crit_enable.attr,
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_alarm_mask.attr,
+	&dev_attr_gpio.attr,
+	&dev_attr_gpio_mask.attr,
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm2.attr,
+	&dev_attr_pwm3.attr,
+	&dev_attr_pwm1_enable.attr,
+	&dev_attr_pwm2_enable.attr,
+	&dev_attr_pwm3_enable.attr,
+	&dev_attr_temp1_auto_point1_pwm.attr,
+	&dev_attr_temp2_auto_point1_pwm.attr,
+	&dev_attr_temp3_auto_point1_pwm.attr,
+	&dev_attr_temp1_auto_point2_pwm.attr,
+	&dev_attr_temp2_auto_point2_pwm.attr,
+	&dev_attr_temp3_auto_point2_pwm.attr,
+	&dev_attr_analog_out.attr,
+	NULL
+};
+
+static const struct attribute_group adm1026_group = {
+	.attrs = adm1026_attributes,
+};
+
 static int adm1026_detect(struct i2c_adapter *adapter, int address,
 			  int kind)
 {
@@ -1554,145 +1674,20 @@
 	adm1026_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1026_group)))
+		goto exitdetach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exitdetach;
+		goto exitremove;
 	}
 
-	device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr);
-	device_create_file(&new_client->dev, 
-		&sensor_dev_attr_temp1_auto_point1_temp.dev_attr);
-	device_create_file(&new_client->dev, 
-		&sensor_dev_attr_temp2_auto_point1_temp.dev_attr);
-	device_create_file(&new_client->dev, 
-		&sensor_dev_attr_temp3_auto_point1_temp.dev_attr);
-	device_create_file(&new_client->dev,
-		&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr);
-	device_create_file(&new_client->dev,
-		&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr);
-	device_create_file(&new_client->dev,
-		&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr);
-	device_create_file(&new_client->dev, 
-		&sensor_dev_attr_temp1_auto_point2_temp.dev_attr);
-	device_create_file(&new_client->dev, 
-		&sensor_dev_attr_temp2_auto_point2_temp.dev_attr);
-	device_create_file(&new_client->dev, 
-		&sensor_dev_attr_temp3_auto_point2_temp.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
-	device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
-	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-	device_create_file(&new_client->dev, &dev_attr_vrm);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_alarm_mask);
-	device_create_file(&new_client->dev, &dev_attr_gpio);
-	device_create_file(&new_client->dev, &dev_attr_gpio_mask);
-	device_create_file(&new_client->dev, &dev_attr_pwm1);
-	device_create_file(&new_client->dev, &dev_attr_pwm2);
-	device_create_file(&new_client->dev, &dev_attr_pwm3);
-	device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-	device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
-	device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
-	device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm);
-	device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm);
-	device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm);
-	device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm);
-	device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm);
-	device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm);
-	device_create_file(&new_client->dev, &dev_attr_analog_out);
 	return 0;
 
 	/* Error out and cleanup code */
+exitremove:
+	sysfs_remove_group(&new_client->dev.kobj, &adm1026_group);
 exitdetach:
 	i2c_detach_client(new_client);
 exitfree:
@@ -1700,6 +1695,17 @@
 exit:
 	return err;
 }
+
+static int adm1026_detach_client(struct i2c_client *client)
+{
+	struct adm1026_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
+	i2c_detach_client(client);
+	kfree(data);
+	return 0;
+}
+
 static int __init sm_adm1026_init(void)
 {
 	return i2c_add_driver(&adm1026_driver);
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 3bf2da6..122683f 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -730,6 +730,61 @@
 	return i2c_probe(adapter, &addr_data, adm1031_detect);
 }
 
+static struct attribute *adm1031_attributes[] = {
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_pwm1.attr,
+	&dev_attr_auto_fan1_channel.attr,
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_crit.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp2_min.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp2_crit.attr,
+
+	&dev_attr_auto_temp1_off.attr,
+	&dev_attr_auto_temp1_min.attr,
+	&dev_attr_auto_temp1_max.attr,
+
+	&dev_attr_auto_temp2_off.attr,
+	&dev_attr_auto_temp2_min.attr,
+	&dev_attr_auto_temp2_max.attr,
+
+	&dev_attr_auto_fan1_min_pwm.attr,
+
+	&dev_attr_alarms.attr,
+
+	NULL
+};
+
+static const struct attribute_group adm1031_group = {
+	.attrs = adm1031_attributes,
+};
+
+static struct attribute *adm1031_attributes_opt[] = {
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_div.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_pwm2.attr,
+	&dev_attr_auto_fan2_channel.attr,
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp3_min.attr,
+	&dev_attr_temp3_max.attr,
+	&dev_attr_temp3_crit.attr,
+	&dev_attr_auto_temp3_off.attr,
+	&dev_attr_auto_temp3_min.attr,
+	&dev_attr_auto_temp3_max.attr,
+	&dev_attr_auto_fan2_min_pwm.attr,
+	NULL
+};
+
+static const struct attribute_group adm1031_group_opt = {
+	.attrs = adm1031_attributes_opt,
+};
+
 /* This function is called by i2c_probe */
 static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -789,57 +844,26 @@
 	adm1031_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1031_group)))
+		goto exit_detach;
+
+	if (kind == adm1031) {
+		if ((err = sysfs_create_group(&new_client->dev.kobj,
+						&adm1031_group_opt)))
+			goto exit_remove;
+	}
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
-	}
-
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_pwm1);
-	device_create_file(&new_client->dev, &dev_attr_auto_fan1_channel);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-
-	device_create_file(&new_client->dev, &dev_attr_auto_temp1_off);
-	device_create_file(&new_client->dev, &dev_attr_auto_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_auto_temp1_max);
-
-	device_create_file(&new_client->dev, &dev_attr_auto_temp2_off);
-	device_create_file(&new_client->dev, &dev_attr_auto_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_auto_temp2_max);
-
-	device_create_file(&new_client->dev, &dev_attr_auto_fan1_min_pwm);
-
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
-	if (kind == adm1031) {
-		device_create_file(&new_client->dev, &dev_attr_fan2_input);
-		device_create_file(&new_client->dev, &dev_attr_fan2_div);
-		device_create_file(&new_client->dev, &dev_attr_fan2_min);
-		device_create_file(&new_client->dev, &dev_attr_pwm2);
-		device_create_file(&new_client->dev,
-				   &dev_attr_auto_fan2_channel);
-		device_create_file(&new_client->dev, &dev_attr_temp3_input);
-		device_create_file(&new_client->dev, &dev_attr_temp3_min);
-		device_create_file(&new_client->dev, &dev_attr_temp3_max);
-		device_create_file(&new_client->dev, &dev_attr_temp3_crit);
-		device_create_file(&new_client->dev, &dev_attr_auto_temp3_off);
-		device_create_file(&new_client->dev, &dev_attr_auto_temp3_min);
-		device_create_file(&new_client->dev, &dev_attr_auto_temp3_max);
-		device_create_file(&new_client->dev, &dev_attr_auto_fan2_min_pwm);
+		goto exit_remove;
 	}
 
 	return 0;
 
+exit_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &adm1031_group);
+	sysfs_remove_group(&new_client->dev.kobj, &adm1031_group_opt);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -854,6 +878,8 @@
 	int ret;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
+	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
 	if ((ret = i2c_detach_client(client)) != 0) {
 		return ret;
 	}
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 43f6991..377961c 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -465,6 +465,45 @@
 }
 static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
 
+static struct attribute *adm9240_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&dev_attr_temp1_input.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_aout_output.attr,
+	&dev_attr_chassis_clear.attr,
+	&dev_attr_cpu0_vid.attr,
+	NULL
+};
+
+static const struct attribute_group adm9240_group = {
+	.attrs = adm9240_attributes,
+};
+
 
 /*** sensor chip detect and driver install ***/
 
@@ -548,72 +587,19 @@
 	adm9240_init_client(new_client);
 
 	/* populate sysfs filesystem */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove;
 	}
 
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in0_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in0_min.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in0_max.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in1_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in1_min.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in1_max.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in2_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in2_min.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in2_max.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in3_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in3_min.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in3_max.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in4_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in4_min.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in4_max.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in5_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in5_min.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_in5_max.dev_attr);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_temp1_max.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_temp1_max_hyst.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_fan1_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_fan1_div.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_fan1_min.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_fan2_input.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_fan2_div.dev_attr);
-	device_create_file(&new_client->dev,
-			&sensor_dev_attr_fan2_min.dev_attr);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_aout_output);
-	device_create_file(&new_client->dev, &dev_attr_chassis_clear);
-	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-
 	return 0;
 
+exit_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &adm9240_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -635,6 +621,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &adm9240_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index facc1cc..57b1c7b 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -298,12 +298,6 @@
 sysfs_in(5);
 sysfs_in(6);
 
-#define device_create_file_in(client, offset) do { \
-	device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-	device_create_file(&client->dev, &dev_attr_in##offset##_min); \
-	device_create_file(&client->dev, &dev_attr_in##offset##_max); \
-} while (0)
-
 /* 3 Fans */
 static ssize_t show_fan(struct device *dev, char *buf, int nr)
 {
@@ -421,12 +415,6 @@
 sysfs_fan(2);
 sysfs_fan(3);
 
-#define device_create_file_fan(client, offset) do { \
-	device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-	device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
-	device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-} while (0)
-
 /* 4 Temp. Sensors */
 static int sprintf_temp_from_reg(u16 reg, char *buf, int nr)
 {
@@ -515,12 +503,6 @@
 sysfs_temp(4);
 
 /* VID */
-#define device_create_file_temp(client, num) do { \
-	device_create_file(&client->dev, &dev_attr_temp##num##_input); \
-	device_create_file(&client->dev, &dev_attr_temp##num##_max); \
-	device_create_file(&client->dev, &dev_attr_temp##num##_max_hyst); \
-} while (0)
-
 static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
@@ -528,8 +510,6 @@
 }
 
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 /* VRM */
 static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
@@ -549,8 +529,6 @@
 
 /* Alarms */
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm);
 
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -559,8 +537,6 @@
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-#define device_create_file_alarms(client) \
-device_create_file(&client->dev, &dev_attr_alarms)
 
 /* 1 PWM */
 static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf)
@@ -607,10 +583,65 @@
 static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1);
 static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
 		show_pwm_enable1, set_pwm_enable1);
-#define device_create_file_pwm1(client) do { \
-	device_create_file(&new_client->dev, &dev_attr_pwm1); \
-	device_create_file(&new_client->dev, &dev_attr_pwm1_enable); \
-} while (0)
+
+static struct attribute *asb100_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+	&dev_attr_in5_input.attr,
+	&dev_attr_in5_min.attr,
+	&dev_attr_in5_max.attr,
+	&dev_attr_in6_input.attr,
+	&dev_attr_in6_min.attr,
+	&dev_attr_in6_max.attr,
+
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan2_div.attr,
+	&dev_attr_fan3_input.attr,
+	&dev_attr_fan3_min.attr,
+	&dev_attr_fan3_div.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp2_max_hyst.attr,
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp3_max.attr,
+	&dev_attr_temp3_max_hyst.attr,
+	&dev_attr_temp4_input.attr,
+	&dev_attr_temp4_max.attr,
+	&dev_attr_temp4_max_hyst.attr,
+
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm1_enable.attr,
+
+	NULL
+};
+
+static const struct attribute_group asb100_group = {
+	.attrs = asb100_attributes,
+};
 
 /* This function is called when:
 	asb100_driver is inserted (when this module is loaded), for each
@@ -810,38 +841,19 @@
 	data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &asb100_group)))
+		goto ERROR3;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto ERROR3;
+		goto ERROR4;
 	}
 
-	device_create_file_in(new_client, 0);
-	device_create_file_in(new_client, 1);
-	device_create_file_in(new_client, 2);
-	device_create_file_in(new_client, 3);
-	device_create_file_in(new_client, 4);
-	device_create_file_in(new_client, 5);
-	device_create_file_in(new_client, 6);
-
-	device_create_file_fan(new_client, 1);
-	device_create_file_fan(new_client, 2);
-	device_create_file_fan(new_client, 3);
-
-	device_create_file_temp(new_client, 1);
-	device_create_file_temp(new_client, 2);
-	device_create_file_temp(new_client, 3);
-	device_create_file_temp(new_client, 4);
-
-	device_create_file_vid(new_client);
-	device_create_file_vrm(new_client);
-
-	device_create_file_alarms(new_client);
-
-	device_create_file_pwm1(new_client);
-
 	return 0;
 
+ERROR4:
+	sysfs_remove_group(&new_client->dev.kobj, &asb100_group);
 ERROR3:
 	i2c_detach_client(data->lm75[1]);
 	i2c_detach_client(data->lm75[0]);
@@ -861,8 +873,10 @@
 	int err;
 
 	/* main client */
-	if (data)
+	if (data) {
 		hwmon_device_unregister(data->class_dev);
+		sysfs_remove_group(&client->dev.kobj, &asb100_group);
+	}
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 728a1e8..0ccdd07 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -27,6 +27,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
@@ -116,8 +117,7 @@
 {
 	struct atxp1_data *data;
 	struct i2c_client *client;
-	char vid;
-	char cvid;
+	int vid, cvid;
 	unsigned int vcore;
 
 	client = to_i2c_client(dev);
@@ -251,6 +251,17 @@
 */
 static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
 
+static struct attribute *atxp1_attributes[] = {
+	&dev_attr_gpio1.attr,
+	&dev_attr_gpio2.attr,
+	&dev_attr_cpu0_vid.attr,
+	NULL
+};
+
+static const struct attribute_group atxp1_group = {
+	.attrs = atxp1_attributes,
+};
+
 
 static int atxp1_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -320,21 +331,23 @@
 		goto exit_free;
 	}
 
+	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_gpio1);
-	device_create_file(&new_client->dev, &dev_attr_gpio2);
-	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-
 	dev_info(&new_client->dev, "Using VRM: %d.%d\n",
 			 data->vrm / 10, data->vrm % 10);
 
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &atxp1_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -349,6 +362,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &atxp1_group);
 
 	err = i2c_detach_client(client);
 
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 478eb4b..c849c0c 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -29,6 +29,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include "lm75.h"
 
 /* Addresses to scan */
@@ -178,6 +179,18 @@
 static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min);
 static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
 
+static struct attribute *ds1621_attributes[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group ds1621_group = {
+	.attrs = ds1621_attributes,
+};
+
 
 static int ds1621_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -253,21 +266,19 @@
 	ds1621_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &ds1621_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	
 	return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
+      exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &ds1621_group);
       exit_detach:
 	i2c_detach_client(new_client);
       exit_free:
@@ -282,6 +293,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &ds1621_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index fd72440..de17a72 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1,7 +1,7 @@
 /*
  * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
  *             hardware monitoring features
- * Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2005-2006  Jean Delvare <khali@linux-fr.org>
  *
  * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
  * complete hardware monitoring features: voltage, fan and temperature
@@ -31,6 +31,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 static struct platform_device *pdev;
@@ -147,7 +148,7 @@
 	u8 temp_high[3];
 	u8 temp_hyst[3];
 	u8 temp_mode;
-	u8 alarms[3];
+	unsigned long alarms;
 };
 
 static inline long in_from_reg(u8 reg)
@@ -311,10 +312,9 @@
 			data->temp[nr] = f71805f_read8(data,
 					 F71805F_REG_TEMP(nr));
 		}
-		for (nr = 0; nr < 3; nr++) {
-			data->alarms[nr] = f71805f_read8(data,
-					   F71805F_REG_STATUS(nr));
-		}
+		data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0))
+			+ (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8)
+			+ (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -557,8 +557,7 @@
 {
 	struct f71805f_data *data = f71805f_update_device(dev);
 
-	return sprintf(buf, "%d\n", data->alarms[0] |
-				    ((data->alarms[1] & 0x01) << 8));
+	return sprintf(buf, "%lu\n", data->alarms & 0x1ff);
 }
 
 static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
@@ -566,7 +565,7 @@
 {
 	struct f71805f_data *data = f71805f_update_device(dev);
 
-	return sprintf(buf, "%d\n", data->alarms[2] & 0x07);
+	return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07);
 }
 
 static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
@@ -574,7 +573,17 @@
 {
 	struct f71805f_data *data = f71805f_update_device(dev);
 
-	return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
+	return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07);
+}
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute
+			  *devattr, char *buf)
+{
+	struct f71805f_data *data = f71805f_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int bitnr = attr->index;
+
+	return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1);
 }
 
 static ssize_t show_name(struct device *dev, struct device_attribute
@@ -585,88 +594,189 @@
 	return sprintf(buf, "%s\n", data->name);
 }
 
-static struct device_attribute f71805f_dev_attr[] = {
-	__ATTR(in0_input, S_IRUGO, show_in0, NULL),
-	__ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max),
-	__ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min),
-	__ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL),
-	__ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL),
-	__ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL),
-	__ATTR(name, S_IRUGO, show_name, NULL),
+static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
+static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
+static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 1);
+static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 2);
+static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 3);
+static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 4);
+static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 5);
+static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 6);
+static SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
+static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 7);
+static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 7);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
+static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR,
+			  show_in_max, set_in_max, 8);
+static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
+			  show_in_min, set_in_min, 8);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
+			  show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
+			  show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
+			  show_fan_min, set_fan_min, 2);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
+		    show_temp_max, set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
+		    show_temp_hyst, set_temp_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
+		    show_temp_max, set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
+		    show_temp_hyst, set_temp_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,
+		    show_temp_max, set_temp_max, 2);
+static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
+		    show_temp_hyst, set_temp_hyst, 2);
+static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
+static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
+static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct attribute *f71805f_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in0_min.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in7_max.dev_attr.attr,
+	&sensor_dev_attr_in7_min.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in8_max.dev_attr.attr,
+	&sensor_dev_attr_in8_min.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_type.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_type.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_type.dev_attr.attr,
+
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
+	&sensor_dev_attr_in6_alarm.dev_attr.attr,
+	&sensor_dev_attr_in7_alarm.dev_attr.attr,
+	&sensor_dev_attr_in8_alarm.dev_attr.attr,
+	&dev_attr_alarms_in.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
+	&dev_attr_alarms_temp.attr,
+	&dev_attr_alarms_fan.attr,
+
+	&dev_attr_name.attr,
+	NULL
 };
 
-static struct sensor_device_attribute f71805f_sensor_attr[] = {
-	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
-	SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 1),
-	SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 1),
-	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
-	SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 2),
-	SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 2),
-	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
-	SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 3),
-	SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 3),
-	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
-	SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 4),
-	SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 4),
-	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
-	SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 5),
-	SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 5),
-	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
-	SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 6),
-	SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 6),
-	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
-	SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 7),
-	SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 7),
-	SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
-	SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR,
-		    show_in_max, set_in_max, 8),
-	SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR,
-		    show_in_min, set_in_min, 8),
-
-	SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
-	SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
-		    show_temp_max, set_temp_max, 0),
-	SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
-		    show_temp_hyst, set_temp_hyst, 0),
-	SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
-	SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
-	SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
-		    show_temp_max, set_temp_max, 1),
-	SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
-		    show_temp_hyst, set_temp_hyst, 1),
-	SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
-	SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
-	SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
-		    show_temp_max, set_temp_max, 2),
-	SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
-		    show_temp_hyst, set_temp_hyst, 2),
-	SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
+static const struct attribute_group f71805f_group = {
+	.attrs = f71805f_attributes,
 };
 
-static struct sensor_device_attribute f71805f_fan_attr[] = {
-	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
-	SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR,
-		    show_fan_min, set_fan_min, 0),
-	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
-	SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR,
-		    show_fan_min, set_fan_min, 1),
-	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
-	SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR,
-		    show_fan_min, set_fan_min, 2),
+static struct attribute *f71805f_attributes_fan[3][4] = {
+	{
+		&sensor_dev_attr_fan1_input.dev_attr.attr,
+		&sensor_dev_attr_fan1_min.dev_attr.attr,
+		&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan2_input.dev_attr.attr,
+		&sensor_dev_attr_fan2_min.dev_attr.attr,
+		&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan3_input.dev_attr.attr,
+		&sensor_dev_attr_fan3_min.dev_attr.attr,
+		&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+		NULL
+	}
+};
+
+static const struct attribute_group f71805f_group_fan[3] = {
+	{ .attrs = f71805f_attributes_fan[0] },
+	{ .attrs = f71805f_attributes_fan[1] },
+	{ .attrs = f71805f_attributes_fan[2] },
 };
 
 /*
@@ -714,43 +824,35 @@
 
 	platform_set_drvdata(pdev, data);
 
-	data->class_dev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
-		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
-		goto exit_free;
-	}
-
 	/* Initialize the F71805F chip */
 	f71805f_init_device(data);
 
 	/* Register sysfs interface files */
-	for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) {
-		err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]);
-		if (err)
-			goto exit_class;
-	}
-	for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) {
-		err = device_create_file(&pdev->dev,
-					 &f71805f_sensor_attr[i].dev_attr);
-		if (err)
-			goto exit_class;
-	}
-	for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) {
-		if (!(data->fan_enabled & (1 << (i / 2))))
+	if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
+		goto exit_free;
+	for (i = 0; i < 3; i++) {
+		if (!(data->fan_enabled & (1 << i)))
 			continue;
-		err = device_create_file(&pdev->dev,
-					 &f71805f_fan_attr[i].dev_attr);
-		if (err)
-			goto exit_class;
+		if ((err = sysfs_create_group(&pdev->dev.kobj,
+					      &f71805f_group_fan[i])))
+			goto exit_remove_files;
+	}
+
+	data->class_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+		goto exit_remove_files;
 	}
 
 	return 0;
 
-exit_class:
-	dev_err(&pdev->dev, "Sysfs interface creation failed\n");
-	hwmon_device_unregister(data->class_dev);
+exit_remove_files:
+	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
+	for (i = 0; i < 3; i++)
+		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
 exit_free:
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 exit:
 	return err;
@@ -759,9 +861,13 @@
 static int __devexit f71805f_remove(struct platform_device *pdev)
 {
 	struct f71805f_data *data = platform_get_drvdata(pdev);
+	int i;
 
 	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
+	for (i = 0; i < 3; i++)
+		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
 	kfree(data);
 
 	return 0;
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index 6bc76b4..1971775 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -34,6 +34,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -240,47 +241,45 @@
 sysfs_control(FSCHER_REG_CONTROL)
 sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET)
   
-#define device_create_file_fan(client, offset) \
-do { \
-	device_create_file(&client->dev, &dev_attr_fan##offset##_status); \
-	device_create_file(&client->dev, &dev_attr_pwm##offset); \
-	device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-	device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-} while (0)
+static struct attribute *fscher_attributes[] = {
+	&dev_attr_revision.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_control.attr,
 
-#define device_create_file_temp(client, offset) \
-do { \
-	device_create_file(&client->dev, &dev_attr_temp##offset##_status); \
-	device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
-} while (0)
+	&dev_attr_watchdog_status.attr,
+	&dev_attr_watchdog_control.attr,
+	&dev_attr_watchdog_preset.attr,
 
-#define device_create_file_in(client, offset) \
-do { \
-	device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-} while (0)
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
 
-#define device_create_file_revision(client) \
-do { \
-	device_create_file(&client->dev, &dev_attr_revision); \
-} while (0)
+	&dev_attr_fan1_status.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan1_input.attr,
+	&dev_attr_pwm1.attr,
+	&dev_attr_fan2_status.attr,
+	&dev_attr_fan2_div.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_pwm2.attr,
+	&dev_attr_fan3_status.attr,
+	&dev_attr_fan3_div.attr,
+	&dev_attr_fan3_input.attr,
+	&dev_attr_pwm3.attr,
 
-#define device_create_file_alarms(client) \
-do { \
-	device_create_file(&client->dev, &dev_attr_alarms); \
-} while (0)
+	&dev_attr_temp1_status.attr,
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_status.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp3_status.attr,
+	&dev_attr_temp3_input.attr,
+	NULL
+};
 
-#define device_create_file_control(client) \
-do { \
-	device_create_file(&client->dev, &dev_attr_control); \
-} while (0)
+static const struct attribute_group fscher_group = {
+	.attrs = fscher_attributes,
+};
 
-#define device_create_file_watchdog(client) \
-do { \
-	device_create_file(&client->dev, &dev_attr_watchdog_status); \
-	device_create_file(&client->dev, &dev_attr_watchdog_control); \
-	device_create_file(&client->dev, &dev_attr_watchdog_preset); \
-} while (0)
-  
 /*
  * Real code
  */
@@ -342,31 +341,19 @@
 	fscher_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file_revision(new_client);
-	device_create_file_alarms(new_client);
-	device_create_file_control(new_client);
-	device_create_file_watchdog(new_client);
-
-	device_create_file_in(new_client, 0);
-	device_create_file_in(new_client, 1);
-	device_create_file_in(new_client, 2);
-
-	device_create_file_fan(new_client, 1);
-	device_create_file_fan(new_client, 2);
-	device_create_file_fan(new_client, 3);
-
-	device_create_file_temp(new_client, 1);
-	device_create_file_temp(new_client, 2);
-	device_create_file_temp(new_client, 3);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &fscher_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -381,6 +368,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &fscher_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 6dc4846b..ea506a77f9 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -38,6 +38,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -432,6 +433,44 @@
 static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
 static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
 
+static struct attribute *fscpos_attributes[] = {
+	&dev_attr_event.attr,
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
+
+	&dev_attr_wdog_control.attr,
+	&dev_attr_wdog_preset.attr,
+	&dev_attr_wdog_state.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_status.attr,
+	&dev_attr_temp1_reset.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp2_status.attr,
+	&dev_attr_temp2_reset.attr,
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp3_status.attr,
+	&dev_attr_temp3_reset.attr,
+
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_status.attr,
+	&dev_attr_fan1_ripple.attr,
+	&dev_attr_pwm1.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_status.attr,
+	&dev_attr_fan2_ripple.attr,
+	&dev_attr_pwm2.attr,
+	&dev_attr_fan3_input.attr,
+	&dev_attr_fan3_status.attr,
+	&dev_attr_fan3_ripple.attr,
+	NULL
+};
+
+static const struct attribute_group fscpos_group = {
+	.attrs = fscpos_attributes,
+};
+
 static int fscpos_attach_adapter(struct i2c_adapter *adapter)
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
@@ -497,42 +536,19 @@
 	dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_event);
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_wdog_control);
-	device_create_file(&new_client->dev, &dev_attr_wdog_preset);
-	device_create_file(&new_client->dev, &dev_attr_wdog_state);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_status);
-	device_create_file(&new_client->dev, &dev_attr_temp1_reset);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_status);
-	device_create_file(&new_client->dev, &dev_attr_temp2_reset);
-	device_create_file(&new_client->dev, &dev_attr_temp3_input);
-	device_create_file(&new_client->dev, &dev_attr_temp3_status);
-	device_create_file(&new_client->dev, &dev_attr_temp3_reset);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_status);
-	device_create_file(&new_client->dev, &dev_attr_fan1_ripple);
-	device_create_file(&new_client->dev, &dev_attr_pwm1);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_status);
-	device_create_file(&new_client->dev, &dev_attr_fan2_ripple);
-	device_create_file(&new_client->dev, &dev_attr_pwm2);
-	device_create_file(&new_client->dev, &dev_attr_fan3_input);
-	device_create_file(&new_client->dev, &dev_attr_fan3_status);
-	device_create_file(&new_client->dev, &dev_attr_fan3_ripple);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &fscpos_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -547,6 +563,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &fscpos_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 6606aab..c103640 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -44,6 +44,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
@@ -340,6 +341,42 @@
 static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO,
 	show_beep_mask, set_beep_mask);
 
+static struct attribute *gl518_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_max.attr,
+
+	&dev_attr_fan1_auto.attr,
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_div.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+
+	&dev_attr_alarms.attr,
+	&dev_attr_beep_enable.attr,
+	&dev_attr_beep_mask.attr,
+	NULL
+};
+
+static const struct attribute_group gl518_group = {
+	.attrs = gl518_attributes,
+};
+
 /*
  * Real code
  */
@@ -420,43 +457,19 @@
 	gl518_init_client((struct i2c_client *) new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &gl518_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_fan1_auto);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_beep_enable);
-	device_create_file(&new_client->dev, &dev_attr_beep_mask);
-
 	return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
-
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &gl518_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -490,6 +503,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &gl518_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 14e810f..ebe7b9a 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -30,6 +30,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /* Type of the extra sensor */
 static unsigned short extra_sensor_type;
@@ -190,55 +191,29 @@
 #define sysfs_vid(n) \
 sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT)
 
-#define device_create_file_vid(client, n) \
-device_create_file(&client->dev, &dev_attr_cpu##n##_vid)
-
 #define sysfs_in(n) \
 sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \
 sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \
 sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \
 
-#define device_create_file_in(client, n) \
-({device_create_file(&client->dev, &dev_attr_in##n##_input); \
-device_create_file(&client->dev, &dev_attr_in##n##_min); \
-device_create_file(&client->dev, &dev_attr_in##n##_max);})
-
 #define sysfs_fan(n) \
 sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \
 sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \
 sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV)
 
-#define device_create_file_fan(client, n) \
-({device_create_file(&client->dev, &dev_attr_fan##n##_input); \
-device_create_file(&client->dev, &dev_attr_fan##n##_min); \
-device_create_file(&client->dev, &dev_attr_fan##n##_div);})
-
 #define sysfs_fan_off(n) \
 sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \
 
-#define device_create_file_fan_off(client, n) \
-device_create_file(&client->dev, &dev_attr_fan##n##_off)
-
 #define sysfs_temp(n) \
 sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \
 sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \
 sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST)
 
-#define device_create_file_temp(client, n) \
-({device_create_file(&client->dev, &dev_attr_temp##n##_input); \
-device_create_file(&client->dev, &dev_attr_temp##n##_max); \
-device_create_file(&client->dev, &dev_attr_temp##n##_max_hyst);})
-
 #define sysfs_alarms() \
 sysfs_ro(alarms, , GL520_REG_ALARMS) \
 sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \
 sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK)
 
-#define device_create_file_alarms(client) \
-({device_create_file(&client->dev, &dev_attr_alarms); \
-device_create_file(&client->dev, &dev_attr_beep_enable); \
-device_create_file(&client->dev, &dev_attr_beep_mask);})
-
 
 sysfs_vid(0)
 
@@ -511,6 +486,59 @@
 	return count;
 }
 
+static struct attribute *gl520_attributes[] = {
+	&dev_attr_cpu0_vid.attr,
+
+	&dev_attr_in0_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in3_max.attr,
+
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan1_off.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan2_div.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+
+	&dev_attr_alarms.attr,
+	&dev_attr_beep_enable.attr,
+	&dev_attr_beep_mask.attr,
+	NULL
+};
+
+static const struct attribute_group gl520_group = {
+	.attrs = gl520_attributes,
+};
+
+static struct attribute *gl520_attributes_opt[] = {
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp2_max_hyst.attr,
+	NULL
+};
+
+static const struct attribute_group gl520_group_opt = {
+	.attrs = gl520_attributes_opt,
+};
+
 
 /*
  * Real code
@@ -572,33 +600,39 @@
 	gl520_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &gl520_group)))
+		goto exit_detach;
+
+	if (data->two_temps) {
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_temp2_input))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_temp2_max))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_temp2_max_hyst)))
+			goto exit_remove_files;
+	} else {
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_in4_input))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_in4_min))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_in4_max)))
+			goto exit_remove_files;
+	}
+
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file_vid(new_client, 0);
-
-	device_create_file_in(new_client, 0);
-	device_create_file_in(new_client, 1);
-	device_create_file_in(new_client, 2);
-	device_create_file_in(new_client, 3);
-	if (!data->two_temps)
-		device_create_file_in(new_client, 4);
-
-	device_create_file_fan(new_client, 1);
-	device_create_file_fan(new_client, 2);
-	device_create_file_fan_off(new_client, 1);
-
-	device_create_file_temp(new_client, 1);
-	if (data->two_temps)
-		device_create_file_temp(new_client, 2);
-
-	device_create_file_alarms(new_client);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &gl520_group);
+	sysfs_remove_group(&new_client->dev.kobj, &gl520_group_opt);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -652,6 +686,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &gl520_group);
+	sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 42b6328..8e7b560 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -587,7 +587,9 @@
 	input_set_abs_params(hdaps_idev, ABS_Y,
 			-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
 
-	input_register_device(hdaps_idev);
+	ret = input_register_device(hdaps_idev);
+	if (ret)
+		goto out_idev;
 
 	/* start up our timer for the input device */
 	init_timer(&hdaps_timer);
@@ -598,6 +600,8 @@
 	printk(KERN_INFO "hdaps: driver successfully loaded.\n");
 	return 0;
 
+out_idev:
+	input_free_device(hdaps_idev);
 out_group:
 	sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
 out_device:
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index b0ee574..323ef06 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -4,10 +4,12 @@
 
     Supports: IT8705F  Super I/O chip w/LPC interface
               IT8712F  Super I/O chip w/LPC interface & SMBus
+              IT8716F  Super I/O chip w/LPC interface
+              IT8718F  Super I/O chip w/LPC interface
               Sis950   A clone of the IT8705F
 
     Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> 
-    Largely inspired by lm78.c of the same package
+    Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.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
@@ -24,13 +26,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/*
-    djg@pdp8.net David Gesswein 7/18/01
-    Modified to fix bug with not all alarms enabled.
-    Added ability to read battery voltage and select temperature sensor
-    type at module load time.
-*/
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -42,6 +37,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 
@@ -50,12 +46,13 @@
 static unsigned short isa_address;
 
 /* Insmod parameters */
-I2C_CLIENT_INSMOD_2(it87, it8712);
+I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718);
 
 #define	REG	0x2e	/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
 #define	VAL	0x2f	/* The value to read/write */
 #define PME	0x04	/* The device with the fan registers in it */
+#define GPIO	0x07	/* The device with the IT8718F VID value in it */
 #define	DEVID	0x20	/* Register: Device ID */
 #define	DEVREV	0x22	/* Register: Device Revision */
 
@@ -77,10 +74,10 @@
 }
 
 static inline void
-superio_select(void)
+superio_select(int ldn)
 {
 	outb(DEV, REG);
-	outb(PME, VAL);
+	outb(ldn, VAL);
 }
 
 static inline void
@@ -99,20 +96,27 @@
 	outb(0x02, VAL);
 }
 
+/* Logical device 4 registers */
 #define IT8712F_DEVID 0x8712
 #define IT8705F_DEVID 0x8705
+#define IT8716F_DEVID 0x8716
+#define IT8718F_DEVID 0x8718
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
+/* Logical device 7 registers (IT8712F and later) */
+#define IT87_SIO_PINX2_REG	0x2c	/* Pin selection */
+#define IT87_SIO_VID_REG	0xfc	/* VID value */
+
 /* Update battery voltage after every reading if true */
 static int update_vbat;
 
 /* Not all BIOSes properly configure the PWM registers */
 static int fix_pwm_polarity;
 
-/* Chip Type */
-
+/* Values read from Super-I/O config space */
 static u16 chip_type;
+static u8 vid_value;
 
 /* Many IT87 constants specified below */
 
@@ -131,13 +135,21 @@
 #define IT87_REG_ALARM2        0x02
 #define IT87_REG_ALARM3        0x03
 
+/* The IT8718F has the VID value in a different register, in Super-I/O
+   configuration space. */
 #define IT87_REG_VID           0x0a
+/* Warning: register 0x0b is used for something completely different in
+   new chips/revisions. I suspect only 16-bit tachometer mode will work
+   for these. */
 #define IT87_REG_FAN_DIV       0x0b
+#define IT87_REG_FAN_16BIT     0x0c
 
 /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
 
 #define IT87_REG_FAN(nr)       (0x0d + (nr))
 #define IT87_REG_FAN_MIN(nr)   (0x10 + (nr))
+#define IT87_REG_FANX(nr)      (0x18 + (nr))
+#define IT87_REG_FANX_MIN(nr)  (0x1b + (nr))
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
@@ -169,7 +181,16 @@
 			     254);
 }
 
+static inline u16 FAN16_TO_REG(long rpm)
+{
+	if (rpm == 0)
+		return 0xffff;
+	return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
+}
+
 #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
+/* The divider is fixed to 2 in 16-bit mode */
+#define FAN16_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:1350000/((val)*2))
 
 #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\
 					((val)+500)/1000),-128,127))
@@ -181,7 +202,7 @@
 static int DIV_TO_REG(int val)
 {
 	int answer = 0;
-	while ((val >>= 1) != 0)
+	while (answer < 7 && (val >>= 1))
 		answer++;
 	return answer;
 }
@@ -203,10 +224,11 @@
 	unsigned long last_updated;	/* In jiffies */
 
 	u8 in[9];		/* Register value */
-	u8 in_max[9];		/* Register value */
-	u8 in_min[9];		/* Register value */
-	u8 fan[3];		/* Register value */
-	u8 fan_min[3];		/* Register value */
+	u8 in_max[8];		/* Register value */
+	u8 in_min[8];		/* Register value */
+	u8 has_fan;		/* Bitfield, fans enabled */
+	u16 fan[3];		/* Register values, possibly combined */
+	u16 fan_min[3];		/* Register values, possibly combined */
 	u8 temp[3];		/* Register value */
 	u8 temp_high[3];	/* Register value */
 	u8 temp_low[3];		/* Register value */
@@ -545,15 +567,15 @@
 
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
-	int i, min[3];
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int min;
 	u8 old;
 
 	mutex_lock(&data->update_lock);
 	old = it87_read_value(client, IT87_REG_FAN_DIV);
 
-	for (i = 0; i < 3; i++)
-		min[i] = FAN_FROM_REG(data->fan_min[i], DIV_FROM_REG(data->fan_div[i]));
+	/* Save fan min limit */
+	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
 
 	switch (nr) {
 	case 0:
@@ -573,10 +595,10 @@
 		val |= 0x1 << 6;
 	it87_write_value(client, IT87_REG_FAN_DIV, val);
 
-	for (i = 0; i < 3; i++) {
-		data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i]));
-		it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]);
-	}
+	/* Restore fan min limit */
+	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
+
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -657,6 +679,59 @@
 show_pwm_offset(2);
 show_pwm_offset(3);
 
+/* A different set of callbacks for 16-bit fans */
+static ssize_t show_fan16(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr]));
+}
+
+static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr]));
+}
+
+static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct it87_data *data = i2c_get_clientdata(client);
+	int val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->fan_min[nr] = FAN16_TO_REG(val);
+	it87_write_value(client, IT87_REG_FAN_MIN(nr),
+			 data->fan_min[nr] & 0xff);
+	it87_write_value(client, IT87_REG_FANX_MIN(nr),
+			 data->fan_min[nr] >> 8);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* We want to use the same sysfs file names as 8-bit fans, but we need
+   different variable names, so we have to use SENSOR_ATTR instead of
+   SENSOR_DEVICE_ATTR. */
+#define show_fan16_offset(offset) \
+static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \
+	= SENSOR_ATTR(fan##offset##_input, S_IRUGO,		\
+		show_fan16, NULL, offset - 1);			\
+static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \
+	= SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_fan16_min, set_fan16_min, offset - 1)
+
+show_fan16_offset(1);
+show_fan16_offset(2);
+show_fan16_offset(3);
+
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -684,8 +759,6 @@
 	return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm)
 
 static ssize_t
 show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -694,8 +767,88 @@
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid)
+
+static struct attribute *it87_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in7_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in7_max.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_type.dev_attr.attr,
+	&sensor_dev_attr_temp2_type.dev_attr.attr,
+	&sensor_dev_attr_temp3_type.dev_attr.attr,
+
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group it87_group = {
+	.attrs = it87_attributes,
+};
+
+static struct attribute *it87_attributes_opt[] = {
+	&sensor_dev_attr_fan1_input16.dev_attr.attr,
+	&sensor_dev_attr_fan1_min16.dev_attr.attr,
+	&sensor_dev_attr_fan2_input16.dev_attr.attr,
+	&sensor_dev_attr_fan2_min16.dev_attr.attr,
+	&sensor_dev_attr_fan3_input16.dev_attr.attr,
+	&sensor_dev_attr_fan3_min16.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_div.dev_attr.attr,
+
+	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
+
+	&dev_attr_vrm.attr,
+	&dev_attr_cpu0_vid.attr,
+	NULL
+};
+
+static const struct attribute_group it87_group_opt = {
+	.attrs = it87_attributes_opt,
+};
 
 /* This function is called when:
      * it87_driver is inserted (when this module is loaded), for each
@@ -721,10 +874,12 @@
 	superio_enter();
 	chip_type = superio_inw(DEVID);
 	if (chip_type != IT8712F_DEVID
+	 && chip_type != IT8716F_DEVID
+	 && chip_type != IT8718F_DEVID
 	 && chip_type != IT8705F_DEVID)
 	 	goto exit;
 
-	superio_select();
+	superio_select(PME);
 	if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
 		pr_info("it87: Device not activated, skipping\n");
 		goto exit;
@@ -740,6 +895,21 @@
 	pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
 		chip_type, *address, superio_inb(DEVREV) & 0x0f);
 
+	/* Read GPIO config and VID value from LDN 7 (GPIO) */
+	if (chip_type != IT8705F_DEVID) {
+		int reg;
+
+		superio_select(GPIO);
+		if (chip_type == it8718)
+			vid_value = superio_inb(IT87_SIO_VID_REG);
+
+		reg = superio_inb(IT87_SIO_PINX2_REG);
+		if (reg & (1 << 0))
+			pr_info("it87: in3 is VCC (+5V)\n");
+		if (reg & (1 << 1))
+			pr_info("it87: in7 is VCCH (+5V Stand-By)\n");
+	}
+
 exit:
 	superio_exit();
 	return err;
@@ -800,8 +970,19 @@
 		i = it87_read_value(new_client, IT87_REG_CHIPID);
 		if (i == 0x90) {
 			kind = it87;
-			if ((is_isa) && (chip_type == IT8712F_DEVID))
-				kind = it8712;
+			if (is_isa) {
+				switch (chip_type) {
+				case IT8712F_DEVID:
+					kind = it8712;
+					break;
+				case IT8716F_DEVID:
+					kind = it8716;
+					break;
+				case IT8718F_DEVID:
+					kind = it8718;
+					break;
+				}
+			}
 		}
 		else {
 			if (kind == 0)
@@ -818,6 +999,10 @@
 		name = "it87";
 	} else if (kind == it8712) {
 		name = "it8712";
+	} else if (kind == it8716) {
+		name = "it8716";
+	} else if (kind == it8718) {
+		name = "it8718";
 	}
 
 	/* Fill in the remaining client fields and put it into the global list */
@@ -842,76 +1027,103 @@
 	it87_init_client(new_client, data);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &it87_group)))
+		goto ERROR3;
+
+	/* Do not create fan files for disabled fans */
+	if (data->type == it8716 || data->type == it8718) {
+		/* 16-bit tachometers */
+		if (data->has_fan & (1 << 0)) {
+			if ((err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan1_input16.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan1_min16.dev_attr)))
+				goto ERROR4;
+		}
+		if (data->has_fan & (1 << 1)) {
+			if ((err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan2_input16.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan2_min16.dev_attr)))
+				goto ERROR4;
+		}
+		if (data->has_fan & (1 << 2)) {
+			if ((err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan3_input16.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan3_min16.dev_attr)))
+				goto ERROR4;
+		}
+	} else {
+		/* 8-bit tachometers with clock divider */
+		if (data->has_fan & (1 << 0)) {
+			if ((err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan1_input.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan1_min.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan1_div.dev_attr)))
+				goto ERROR4;
+		}
+		if (data->has_fan & (1 << 1)) {
+			if ((err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan2_input.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan2_min.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan2_div.dev_attr)))
+				goto ERROR4;
+		}
+		if (data->has_fan & (1 << 2)) {
+			if ((err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan3_input.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan3_min.dev_attr))
+			 || (err = device_create_file(&new_client->dev,
+			     &sensor_dev_attr_fan3_div.dev_attr)))
+				goto ERROR4;
+		}
+	}
+
+	if (enable_pwm_interface) {
+		if ((err = device_create_file(&new_client->dev,
+		     &sensor_dev_attr_pwm1_enable.dev_attr))
+		 || (err = device_create_file(&new_client->dev,
+		     &sensor_dev_attr_pwm2_enable.dev_attr))
+		 || (err = device_create_file(&new_client->dev,
+		     &sensor_dev_attr_pwm3_enable.dev_attr))
+		 || (err = device_create_file(&new_client->dev,
+		     &sensor_dev_attr_pwm1.dev_attr))
+		 || (err = device_create_file(&new_client->dev,
+		     &sensor_dev_attr_pwm2.dev_attr))
+		 || (err = device_create_file(&new_client->dev,
+		     &sensor_dev_attr_pwm3.dev_attr)))
+			goto ERROR4;
+	}
+
+	if (data->type == it8712 || data->type == it8716
+	 || data->type == it8718) {
+		data->vrm = vid_which_vrm();
+		/* VID reading from Super-I/O config space if available */
+		data->vid = vid_value;
+		if ((err = device_create_file(&new_client->dev,
+		     &dev_attr_vrm))
+		 || (err = device_create_file(&new_client->dev,
+		     &dev_attr_cpu0_vid)))
+			goto ERROR4;
+	}
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto ERROR3;
-	}
-
-	device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
-	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	if (enable_pwm_interface) {
-		device_create_file(&new_client->dev, &sensor_dev_attr_pwm1_enable.dev_attr);
-		device_create_file(&new_client->dev, &sensor_dev_attr_pwm2_enable.dev_attr);
-		device_create_file(&new_client->dev, &sensor_dev_attr_pwm3_enable.dev_attr);
-		device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
-		device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
-		device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
-	}
-
-	if (data->type == it8712) {
-		data->vrm = vid_which_vrm();
-		device_create_file_vrm(new_client);
-		device_create_file_vid(new_client);
+		goto ERROR4;
 	}
 
 	return 0;
 
+ERROR4:
+	sysfs_remove_group(&new_client->dev.kobj, &it87_group);
+	sysfs_remove_group(&new_client->dev.kobj, &it87_group_opt);
 ERROR3:
 	i2c_detach_client(new_client);
 ERROR2:
@@ -929,6 +1141,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &it87_group);
+	sysfs_remove_group(&client->dev.kobj, &it87_group_opt);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
@@ -1045,6 +1259,22 @@
 		data->manual_pwm_ctl[i] = 0xff;
 	}
 
+	/* Some chips seem to have default value 0xff for all limit
+	 * registers. For low voltage limits it makes no sense and triggers
+	 * alarms, so change to 0 instead. For high temperature limits, it
+	 * means -1 degree C, which surprisingly doesn't trigger an alarm,
+	 * but is still confusing, so change to 127 degrees C. */
+	for (i = 0; i < 8; i++) {
+		tmp = it87_read_value(client, IT87_REG_VIN_MIN(i));
+		if (tmp == 0xff)
+			it87_write_value(client, IT87_REG_VIN_MIN(i), 0);
+	}
+	for (i = 0; i < 3; i++) {
+		tmp = it87_read_value(client, IT87_REG_TEMP_HIGH(i));
+		if (tmp == 0xff)
+			it87_write_value(client, IT87_REG_TEMP_HIGH(i), 127);
+	}
+
 	/* Check if temperature channnels are reset manually or by some reason */
 	tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
 	if ((tmp & 0x3f) == 0) {
@@ -1068,6 +1298,18 @@
 		data->fan_main_ctrl |= 0x70;
 		it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
 	}
+	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
+
+	/* Set tachometers to 16-bit mode if needed */
+	if (data->type == it8716 || data->type == it8718) {
+		tmp = it87_read_value(client, IT87_REG_FAN_16BIT);
+		if (~tmp & 0x07 & data->has_fan) {
+			dev_dbg(&client->dev,
+				"Setting fan1-3 to 16-bit mode\n");
+			it87_write_value(client, IT87_REG_FAN_16BIT,
+					 tmp | 0x07);
+		}
+	}
 
 	/* Set current fan mode registers and the default settings for the
 	 * other mode registers */
@@ -1118,18 +1360,26 @@
 			data->in_max[i] =
 			    it87_read_value(client, IT87_REG_VIN_MAX(i));
 		}
+		/* in8 (battery) has no limit registers */
 		data->in[8] =
 		    it87_read_value(client, IT87_REG_VIN(8));
-		/* Temperature sensor doesn't have limit registers, set
-		   to min and max value */
-		data->in_min[8] = 0;
-		data->in_max[8] = 255;
 
 		for (i = 0; i < 3; i++) {
-			data->fan[i] =
-			    it87_read_value(client, IT87_REG_FAN(i));
+			/* Skip disabled fans */
+			if (!(data->has_fan & (1 << i)))
+				continue;
+
 			data->fan_min[i] =
 			    it87_read_value(client, IT87_REG_FAN_MIN(i));
+			data->fan[i] = it87_read_value(client,
+				       IT87_REG_FAN(i));
+			/* Add high byte if in 16-bit mode */
+			if (data->type == it8716 || data->type == it8718) {
+				data->fan[i] |= it87_read_value(client,
+						IT87_REG_FANX(i)) << 8;
+				data->fan_min[i] |= it87_read_value(client,
+						IT87_REG_FANX_MIN(i)) << 8;
+			}
 		}
 		for (i = 0; i < 3; i++) {
 			data->temp[i] =
@@ -1140,10 +1390,14 @@
 			    it87_read_value(client, IT87_REG_TEMP_LOW(i));
 		}
 
-		i = it87_read_value(client, IT87_REG_FAN_DIV);
-		data->fan_div[0] = i & 0x07;
-		data->fan_div[1] = (i >> 3) & 0x07;
-		data->fan_div[2] = (i & 0x40) ? 3 : 1;
+		/* Newer chips don't have clock dividers */
+		if ((data->has_fan & 0x07) && data->type != it8716
+		 && data->type != it8718) {
+			i = it87_read_value(client, IT87_REG_FAN_DIV);
+			data->fan_div[0] = i & 0x07;
+			data->fan_div[1] = (i >> 3) & 0x07;
+			data->fan_div[2] = (i & 0x40) ? 3 : 1;
+		}
 
 		data->alarms =
 			it87_read_value(client, IT87_REG_ALARM1) |
@@ -1153,9 +1407,11 @@
 
 		data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
 		/* The 8705 does not have VID capability */
-		if (data->type == it8712) {
+		if (data->type == it8712 || data->type == it8716) {
 			data->vid = it87_read_value(client, IT87_REG_VID);
-			data->vid &= 0x1f;
+			/* The older IT8712F revisions had only 5 VID pins,
+			   but we assume it is always safe to read 6 bits. */
+			data->vid &= 0x3f;
 		}
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -1193,8 +1449,9 @@
 }
 
 
-MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
-MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
+MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>, "
+	      "Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F, SiS950 driver");
 module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
 module_param(fix_pwm_polarity, bool, 0);
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
new file mode 100644
index 0000000..f58b64e
--- /dev/null
+++ b/drivers/hwmon/k8temp.c
@@ -0,0 +1,294 @@
+/*
+ * k8temp.c - Linux kernel module for hardware monitoring
+ *
+ * Copyright (C) 2006 Rudolf Marek <r.marek@sh.cvut.cz>
+ *
+ * Inspired from the w83785 and amd756 drivers.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/pci.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+#define TEMP_FROM_REG(val)	(((((val) >> 16) & 0xff) - 49) * 1000)
+#define REG_TEMP	0xe4
+#define SEL_PLACE	0x40
+#define SEL_CORE	0x04
+
+struct k8temp_data {
+	struct class_device *class_dev;
+	struct mutex update_lock;
+	const char *name;
+	char valid;		/* zero until following fields are valid */
+	unsigned long last_updated;	/* in jiffies */
+
+	/* registers values */
+	u8 sensorsp;		/* sensor presence bits - SEL_CORE & SEL_PLACE */
+	u32 temp[2][2];		/* core, place */
+};
+
+static struct k8temp_data *k8temp_update_device(struct device *dev)
+{
+	struct k8temp_data *data = dev_get_drvdata(dev);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	u8 tmp;
+
+	mutex_lock(&data->update_lock);
+
+	if (!data->valid
+	    || time_after(jiffies, data->last_updated + HZ)) {
+		pci_read_config_byte(pdev, REG_TEMP, &tmp);
+		tmp &= ~(SEL_PLACE | SEL_CORE);		/* Select sensor 0, core0 */
+		pci_write_config_byte(pdev, REG_TEMP, tmp);
+		pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][0]);
+
+		if (data->sensorsp & SEL_PLACE) {
+			tmp |= SEL_PLACE;	/* Select sensor 1, core0 */
+			pci_write_config_byte(pdev, REG_TEMP, tmp);
+			pci_read_config_dword(pdev, REG_TEMP,
+					      &data->temp[0][1]);
+		}
+
+		if (data->sensorsp & SEL_CORE) {
+			tmp &= ~SEL_PLACE;	/* Select sensor 0, core1 */
+			tmp |= SEL_CORE;
+			pci_write_config_byte(pdev, REG_TEMP, tmp);
+			pci_read_config_dword(pdev, REG_TEMP,
+					      &data->temp[1][0]);
+
+			if (data->sensorsp & SEL_PLACE) {
+				tmp |= SEL_PLACE;	/* Select sensor 1, core1 */
+				pci_write_config_byte(pdev, REG_TEMP, tmp);
+				pci_read_config_dword(pdev, REG_TEMP,
+						      &data->temp[1][1]);
+			}
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
+/*
+ * Sysfs stuff
+ */
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct k8temp_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+
+
+static ssize_t show_temp(struct device *dev,
+			 struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr =
+	    to_sensor_dev_attr_2(devattr);
+	int core = attr->nr;
+	int place = attr->index;
+	struct k8temp_data *data = k8temp_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		       TEMP_FROM_REG(data->temp[core][place]));
+}
+
+/* core, place */
+
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct pci_device_id k8temp_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
+	{ 0 },
+};
+
+MODULE_DEVICE_TABLE(pci, k8temp_ids);
+
+static int __devinit k8temp_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	int err;
+	u8 scfg;
+	u32 temp;
+	struct k8temp_data *data;
+	u32 cpuid = cpuid_eax(1);
+
+	/* this feature should be available since SH-C0 core */
+	if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) {
+		err = -ENODEV;
+		goto exit;
+	}
+
+	if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	pci_read_config_byte(pdev, REG_TEMP, &scfg);
+	scfg &= ~(SEL_PLACE | SEL_CORE);		/* Select sensor 0, core0 */
+	pci_write_config_byte(pdev, REG_TEMP, scfg);
+	pci_read_config_byte(pdev, REG_TEMP, &scfg);
+
+	if (scfg & (SEL_PLACE | SEL_CORE)) {
+		dev_err(&pdev->dev, "Configuration bit(s) stuck at 1!\n");
+		err = -ENODEV;
+		goto exit_free;
+	}
+
+	scfg |= (SEL_PLACE | SEL_CORE);
+	pci_write_config_byte(pdev, REG_TEMP, scfg);
+
+	/* now we know if we can change core and/or sensor */
+	pci_read_config_byte(pdev, REG_TEMP, &data->sensorsp);
+
+	if (data->sensorsp & SEL_PLACE) {
+		scfg &= ~SEL_CORE;	/* Select sensor 1, core0 */
+		pci_write_config_byte(pdev, REG_TEMP, scfg);
+		pci_read_config_dword(pdev, REG_TEMP, &temp);
+		scfg |= SEL_CORE;	/* prepare for next selection */
+		if (!((temp >> 16) & 0xff))	/* if temp is 0 -49C is not likely */
+			data->sensorsp &= ~SEL_PLACE;
+	}
+
+	if (data->sensorsp & SEL_CORE) {
+		scfg &= ~SEL_PLACE;	/* Select sensor 0, core1 */
+		pci_write_config_byte(pdev, REG_TEMP, scfg);
+		pci_read_config_dword(pdev, REG_TEMP, &temp);
+		if (!((temp >> 16) & 0xff))	/* if temp is 0 -49C is not likely */
+			data->sensorsp &= ~SEL_CORE;
+	}
+
+	data->name = "k8temp";
+	mutex_init(&data->update_lock);
+	dev_set_drvdata(&pdev->dev, data);
+
+	/* Register sysfs hooks */
+	err = device_create_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_input.dev_attr);
+	if (err)
+		goto exit_remove;
+
+	/* sensor can be changed and reports something */
+	if (data->sensorsp & SEL_PLACE) {
+		err = device_create_file(&pdev->dev,
+				   &sensor_dev_attr_temp2_input.dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	/* core can be changed and reports something */
+	if (data->sensorsp & SEL_CORE) {
+		err = device_create_file(&pdev->dev,
+				   &sensor_dev_attr_temp3_input.dev_attr);
+		if (err)
+			goto exit_remove;
+		if (data->sensorsp & SEL_PLACE)
+			err = device_create_file(&pdev->dev,
+					   &sensor_dev_attr_temp4_input.
+					   dev_attr);
+			if (err)
+				goto exit_remove;
+	}
+
+	err = device_create_file(&pdev->dev, &dev_attr_name);
+	if (err)
+		goto exit_remove;
+
+	data->class_dev = hwmon_device_register(&pdev->dev);
+
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_input.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp2_input.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp3_input.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp4_input.dev_attr);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+exit_free:
+	dev_set_drvdata(&pdev->dev, NULL);
+	kfree(data);
+exit:
+	return err;
+}
+
+static void __devexit k8temp_remove(struct pci_dev *pdev)
+{
+	struct k8temp_data *data = dev_get_drvdata(&pdev->dev);
+
+	hwmon_device_unregister(data->class_dev);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_input.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp2_input.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp3_input.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp4_input.dev_attr);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	dev_set_drvdata(&pdev->dev, NULL);
+	kfree(data);
+}
+
+static struct pci_driver k8temp_driver = {
+	.name = "k8temp",
+	.id_table = k8temp_ids,
+	.probe = k8temp_probe,
+	.remove = __devexit_p(k8temp_remove),
+};
+
+static int __init k8temp_init(void)
+{
+	return pci_register_driver(&k8temp_driver);
+}
+
+static void __exit k8temp_exit(void)
+{
+	pci_unregister_driver(&k8temp_driver);
+}
+
+MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_DESCRIPTION("AMD K8 core temperature monitor");
+MODULE_LICENSE("GPL");
+
+module_init(k8temp_init)
+module_exit(k8temp_exit)
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 071f0fc..d69f3cf 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -1,7 +1,7 @@
 /*
  * lm63.c - driver for the National Semiconductor LM63 temperature sensor
  *          with integrated fan control
- * Copyright (C) 2004-2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2006  Jean Delvare <khali@linux-fr.org>
  * Based on the lm90 driver.
  *
  * The LM63 is a sensor chip made by National Semiconductor. It measures
@@ -46,6 +46,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -330,6 +331,16 @@
 	return sprintf(buf, "%u\n", data->alarms);
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr,
+			  char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm63_data *data = lm63_update_device(dev);
+	int bitnr = attr->index;
+
+	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
 	set_fan, 1);
@@ -350,8 +361,52 @@
 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
 	set_temp2_crit_hyst);
 
+/* Individual alarm files */
+static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+/* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *lm63_attributes[] = {
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm1_enable.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&dev_attr_temp2_crit_hyst.attr,
+
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group lm63_group = {
+	.attrs = lm63_attributes,
+};
+
+static struct attribute *lm63_attributes_fan1[] = {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_min_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group lm63_group_fan1 = {
+	.attrs = lm63_attributes_fan1,
+};
+
 /*
  * Real code
  */
@@ -438,37 +493,26 @@
 	lm63_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj,
+				      &lm63_group)))
+		goto exit_detach;
+	if (data->config & 0x04) { /* tachometer enabled */
+		if ((err = sysfs_create_group(&new_client->dev.kobj,
+					      &lm63_group_fan1)))
+			goto exit_remove_files;
+	}
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	if (data->config & 0x04) { /* tachometer enabled */
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_fan1_input.dev_attr);
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_fan1_min.dev_attr);
-	}
-	device_create_file(&new_client->dev, &dev_attr_pwm1);
-	device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_input.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_input.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_min.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_max.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_max.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_crit.dev_attr);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
+	sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -518,6 +562,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm63_group);
+	sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index fc25b90..7c65b8b 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -112,6 +112,18 @@
 	return i2c_probe(adapter, &addr_data, lm75_detect);
 }
 
+static struct attribute *lm75_attributes[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm75_group = {
+	.attrs = lm75_attributes,
+};
+
 /* This function is called by i2c_probe */
 static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -199,18 +211,19 @@
 	lm75_init_client(new_client);
 	
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm75_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-
 	return 0;
 
+exit_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &lm75_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -223,6 +236,7 @@
 {
 	struct lm75_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm75_group);
 	i2c_detach_client(client);
 	kfree(data);
 	return 0;
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 459cc97..dd969f1 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -212,6 +212,23 @@
 	return i2c_probe(adapter, &addr_data, lm77_detect);
 }
 
+static struct attribute *lm77_attributes[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_crit.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_crit_hyst.attr,
+	&dev_attr_temp1_min_hyst.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	&dev_attr_alarms.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm77_group = {
+	.attrs = lm77_attributes,
+};
+
 /* This function is called by i2c_probe */
 static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -317,22 +334,19 @@
 	lm77_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
 	return 0;
 
+exit_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &lm77_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -345,6 +359,7 @@
 {
 	struct lm77_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm77_group);
 	i2c_detach_client(client);
 	kfree(data);
 	return 0;
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index fa1715b..ac1b746 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -482,6 +482,50 @@
 	return lm78_detect(adapter, isa_address, -1);
 }
 
+static struct attribute *lm78_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+	&dev_attr_in5_input.attr,
+	&dev_attr_in5_min.attr,
+	&dev_attr_in5_max.attr,
+	&dev_attr_in6_input.attr,
+	&dev_attr_in6_min.attr,
+	&dev_attr_in6_max.attr,
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan2_div.attr,
+	&dev_attr_fan3_input.attr,
+	&dev_attr_fan3_min.attr,
+	&dev_attr_fan3_div.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_cpu0_vid.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm78_group = {
+	.attrs = lm78_attributes,
+};
+
 /* This function is called by i2c_probe */
 static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -616,50 +660,19 @@
 	}
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group)))
+		goto ERROR3;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto ERROR3;
+		goto ERROR4;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
-	device_create_file(&new_client->dev, &dev_attr_in5_input);
-	device_create_file(&new_client->dev, &dev_attr_in5_min);
-	device_create_file(&new_client->dev, &dev_attr_in5_max);
-	device_create_file(&new_client->dev, &dev_attr_in6_input);
-	device_create_file(&new_client->dev, &dev_attr_in6_min);
-	device_create_file(&new_client->dev, &dev_attr_in6_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_fan3_input);
-	device_create_file(&new_client->dev, &dev_attr_fan3_min);
-	device_create_file(&new_client->dev, &dev_attr_fan3_div);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-
 	return 0;
 
+ERROR4:
+	sysfs_remove_group(&new_client->dev.kobj, &lm78_group);
 ERROR3:
 	i2c_detach_client(new_client);
 ERROR2:
@@ -677,6 +690,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm78_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index b4ccdfc..064516d 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -394,6 +394,48 @@
 	return i2c_probe(adapter, &addr_data, lm80_detect);
 }
 
+static struct attribute *lm80_attributes[] = {
+	&dev_attr_in0_min.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in5_min.attr,
+	&dev_attr_in6_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_in4_max.attr,
+	&dev_attr_in5_max.attr,
+	&dev_attr_in6_max.attr,
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in4_input.attr,
+	&dev_attr_in5_input.attr,
+	&dev_attr_in6_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_div.attr,
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	&dev_attr_temp1_crit.attr,
+	&dev_attr_temp1_crit_hyst.attr,
+	&dev_attr_alarms.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm80_group = {
+	.attrs = lm80_attributes,
+};
+
 static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i, cur;
@@ -452,48 +494,19 @@
 	data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm80_group)))
+		goto error_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto error_detach;
+		goto error_remove;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
-	device_create_file(&new_client->dev, &dev_attr_in5_min);
-	device_create_file(&new_client->dev, &dev_attr_in6_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
-	device_create_file(&new_client->dev, &dev_attr_in5_max);
-	device_create_file(&new_client->dev, &dev_attr_in6_max);
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
-	device_create_file(&new_client->dev, &dev_attr_in5_input);
-	device_create_file(&new_client->dev, &dev_attr_in6_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
 	return 0;
 
+error_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &lm80_group);
 error_detach:
 	i2c_detach_client(new_client);
 error_free:
@@ -508,7 +521,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
-
+	sysfs_remove_group(&client->dev.kobj, &lm80_group);
 	if ((err = i2c_detach_client(client)))
 		return err;
 
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 2137d78..feb87b4 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -1,7 +1,7 @@
 /*
  * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2006  Jean Delvare <khali@linux-fr.org>
  *
  * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
  * a sensor chip made by National Semiconductor. It reports up to four
@@ -40,6 +40,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -191,6 +192,16 @@
 	return sprintf(buf, "%d\n", data->alarms);
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute
+			  *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm83_data *data = lm83_update_device(dev);
+	int bitnr = attr->index;
+
+	return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
+}
+
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
 static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
@@ -208,8 +219,64 @@
 static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp,
 	set_temp, 8);
 static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8);
+
+/* Individual alarm files */
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(temp4_input_fault, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15);
+/* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *lm83_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group lm83_group = {
+	.attrs = lm83_attributes,
+};
+
+static struct attribute *lm83_attributes_opt[] = {
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp4_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit.dev_attr.attr,
+
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group lm83_group_opt = {
+	.attrs = lm83_attributes_opt,
+};
+
 /*
  * Real code
  */
@@ -318,59 +385,32 @@
 		goto exit_free;
 
 	/*
-	 * Initialize the LM83 chip
-	 * (Nothing to do for this one.)
-	 */
-
-	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
-	}
-
-	/*
+	 * Register sysfs hooks
 	 * The LM82 can only monitor one external diode which is
 	 * at the same register as the LM83 temp3 entry - so we
 	 * declare 1 and 3 common, and then 2 and 4 only for the LM83.
 	 */
 
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_input.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp3_input.dev_attr);
-
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_max.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp3_max.dev_attr);
-
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_crit.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp3_crit.dev_attr);
-
-	device_create_file(&new_client->dev, &dev_attr_alarms);
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group)))
+		goto exit_detach;
 
 	if (kind == lm83) {
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_temp2_input.dev_attr);
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_temp4_input.dev_attr);
+		if ((err = sysfs_create_group(&new_client->dev.kobj,
+					      &lm83_group_opt)))
+			goto exit_remove_files;
+	}
 
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_temp2_max.dev_attr);
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_temp4_max.dev_attr);
-
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_temp2_crit.dev_attr);
-		device_create_file(&new_client->dev,
-				   &sensor_dev_attr_temp4_crit.dev_attr);
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove_files;
 	}
 
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &lm83_group);
+	sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -385,6 +425,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm83_group);
+	sysfs_remove_group(&client->dev.kobj, &lm83_group_opt);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 342e966..2c3293c 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -1025,6 +1025,89 @@
 	return i2c_probe(adapter, &addr_data, lm85_detect);
 }
 
+static struct attribute *lm85_attributes[] = {
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan3_input.attr,
+	&dev_attr_fan4_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan3_min.attr,
+	&dev_attr_fan4_min.attr,
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm2.attr,
+	&dev_attr_pwm3.attr,
+	&dev_attr_pwm1_enable.attr,
+	&dev_attr_pwm2_enable.attr,
+	&dev_attr_pwm3_enable.attr,
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp2_min.attr,
+	&dev_attr_temp3_min.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp3_max.attr,
+	&dev_attr_vrm.attr,
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_pwm1_auto_channels.attr,
+	&dev_attr_pwm2_auto_channels.attr,
+	&dev_attr_pwm3_auto_channels.attr,
+	&dev_attr_pwm1_auto_pwm_min.attr,
+	&dev_attr_pwm2_auto_pwm_min.attr,
+	&dev_attr_pwm3_auto_pwm_min.attr,
+	&dev_attr_pwm1_auto_pwm_minctl.attr,
+	&dev_attr_pwm2_auto_pwm_minctl.attr,
+	&dev_attr_pwm3_auto_pwm_minctl.attr,
+	&dev_attr_pwm1_auto_pwm_freq.attr,
+	&dev_attr_pwm2_auto_pwm_freq.attr,
+	&dev_attr_pwm3_auto_pwm_freq.attr,
+	&dev_attr_temp1_auto_temp_off.attr,
+	&dev_attr_temp2_auto_temp_off.attr,
+	&dev_attr_temp3_auto_temp_off.attr,
+	&dev_attr_temp1_auto_temp_min.attr,
+	&dev_attr_temp2_auto_temp_min.attr,
+	&dev_attr_temp3_auto_temp_min.attr,
+	&dev_attr_temp1_auto_temp_max.attr,
+	&dev_attr_temp2_auto_temp_max.attr,
+	&dev_attr_temp3_auto_temp_max.attr,
+	&dev_attr_temp1_auto_temp_crit.attr,
+	&dev_attr_temp2_auto_temp_crit.attr,
+	&dev_attr_temp3_auto_temp_crit.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm85_group = {
+	.attrs = lm85_attributes,
+};
+
+static struct attribute *lm85_attributes_opt[] = {
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm85_group_opt = {
+	.attrs = lm85_attributes_opt,
+};
+
 static int lm85_detect(struct i2c_adapter *adapter, int address,
 		int kind)
 {
@@ -1163,87 +1246,33 @@
 	lm85_init_client(new_client);
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm85_group)))
 		goto ERROR2;
-	}
-
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan3_input);
-	device_create_file(&new_client->dev, &dev_attr_fan4_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan3_min);
-	device_create_file(&new_client->dev, &dev_attr_fan4_min);
-	device_create_file(&new_client->dev, &dev_attr_pwm1);
-	device_create_file(&new_client->dev, &dev_attr_pwm2);
-	device_create_file(&new_client->dev, &dev_attr_pwm3);
-	device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-	device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
-	device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp3_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp3_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp3_max);
-	device_create_file(&new_client->dev, &dev_attr_vrm);
-	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_pwm1_auto_channels);
-	device_create_file(&new_client->dev, &dev_attr_pwm2_auto_channels);
-	device_create_file(&new_client->dev, &dev_attr_pwm3_auto_channels);
-	device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_min);
-	device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_min);
-	device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_min);
-	device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_minctl);
-	device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_minctl);
-	device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_minctl);
-	device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_freq);
-	device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_freq);
-	device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_freq);
-	device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_off);
-	device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_off);
-	device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_off);
-	device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_min);
-	device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_max);
-	device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_crit);
 
 	/* The ADT7463 has an optional VRM 10 mode where pin 21 is used
 	   as a sixth digital VID input rather than an analog input. */
 	data->vid = lm85_read_value(new_client, LM85_REG_VID);
-	if (!(kind == adt7463 && (data->vid & 0x80))) {
-		device_create_file(&new_client->dev, &dev_attr_in4_input);
-		device_create_file(&new_client->dev, &dev_attr_in4_min);
-		device_create_file(&new_client->dev, &dev_attr_in4_max);
+	if (!(kind == adt7463 && (data->vid & 0x80)))
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_in4_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in4_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in4_max)))
+			goto ERROR3;
+
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
 	}
 
 	return 0;
 
 	/* Error out and cleanup code */
+    ERROR3:
+	sysfs_remove_group(&new_client->dev.kobj, &lm85_group);
+	sysfs_remove_group(&new_client->dev.kobj, &lm85_group_opt);
     ERROR2:
 	i2c_detach_client(new_client);
     ERROR1:
@@ -1256,6 +1285,8 @@
 {
 	struct lm85_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm85_group);
+	sysfs_remove_group(&client->dev.kobj, &lm85_group_opt);
 	i2c_detach_client(client);
 	kfree(data);
 	return 0;
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index e6c1b63..3ce8254 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -542,6 +542,78 @@
 	return i2c_probe(adapter, &addr_data, lm87_detect);
 }
 
+static struct attribute *lm87_attributes[] = {
+	&dev_attr_in1_input.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp1_crit.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp2_min.attr,
+	&dev_attr_temp2_crit.attr,
+
+	&dev_attr_alarms.attr,
+	&dev_attr_aout_output.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm87_group = {
+	.attrs = lm87_attributes,
+};
+
+static struct attribute *lm87_attributes_opt[] = {
+	&dev_attr_in6_input.attr,
+	&dev_attr_in6_min.attr,
+	&dev_attr_in6_max.attr,
+
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_div.attr,
+
+	&dev_attr_in7_input.attr,
+	&dev_attr_in7_min.attr,
+	&dev_attr_in7_max.attr,
+
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan2_div.attr,
+
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp3_max.attr,
+	&dev_attr_temp3_min.attr,
+	&dev_attr_temp3_crit.attr,
+
+	&dev_attr_in0_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in5_input.attr,
+	&dev_attr_in5_min.attr,
+	&dev_attr_in5_max.attr,
+
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm87_group_opt = {
+	.attrs = lm87_attributes_opt,
+};
+
 /*
  * The following function does more than just detection. If detection
  * succeeds, it also registers the new chip.
@@ -609,77 +681,90 @@
 	data->in_scale[7] = 1875;
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group)))
 		goto exit_detach;
-	}
-
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
 
 	if (data->channel & CHAN_NO_FAN(0)) {
-		device_create_file(&new_client->dev, &dev_attr_in6_input);
-		device_create_file(&new_client->dev, &dev_attr_in6_min);
-		device_create_file(&new_client->dev, &dev_attr_in6_max);
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_in6_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in6_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in6_max)))
+			goto exit_remove;
 	} else {
-		device_create_file(&new_client->dev, &dev_attr_fan1_input);
-		device_create_file(&new_client->dev, &dev_attr_fan1_min);
-		device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	}
-	if (data->channel & CHAN_NO_FAN(1)) {
-		device_create_file(&new_client->dev, &dev_attr_in7_input);
-		device_create_file(&new_client->dev, &dev_attr_in7_min);
-		device_create_file(&new_client->dev, &dev_attr_in7_max);
-	} else {
-		device_create_file(&new_client->dev, &dev_attr_fan2_input);
-		device_create_file(&new_client->dev, &dev_attr_fan2_min);
-		device_create_file(&new_client->dev, &dev_attr_fan2_div);
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_fan1_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_fan1_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_fan1_div)))
+			goto exit_remove;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
+	if (data->channel & CHAN_NO_FAN(1)) {
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_in7_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in7_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in7_max)))
+			goto exit_remove;
+	} else {
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_fan2_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_fan2_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_fan2_div)))
+			goto exit_remove;
+	}
 
 	if (data->channel & CHAN_TEMP3) {
-		device_create_file(&new_client->dev, &dev_attr_temp3_input);
-		device_create_file(&new_client->dev, &dev_attr_temp3_max);
-		device_create_file(&new_client->dev, &dev_attr_temp3_min);
-		device_create_file(&new_client->dev, &dev_attr_temp3_crit);
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_max))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_crit)))
+			goto exit_remove;
 	} else {
-		device_create_file(&new_client->dev, &dev_attr_in0_input);
-		device_create_file(&new_client->dev, &dev_attr_in0_min);
-		device_create_file(&new_client->dev, &dev_attr_in0_max);
-		device_create_file(&new_client->dev, &dev_attr_in5_input);
-		device_create_file(&new_client->dev, &dev_attr_in5_min);
-		device_create_file(&new_client->dev, &dev_attr_in5_max);
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_in0_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in0_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in0_max))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in5_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in5_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in5_max)))
+			goto exit_remove;
 	}
 
 	if (!(data->channel & CHAN_NO_VID)) {
-		device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-		device_create_file(&new_client->dev, &dev_attr_vrm);
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_cpu0_vid))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_vrm)))
+			goto exit_remove;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_aout_output);
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove;
+	}
 
 	return 0;
 
+exit_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &lm87_group);
+	sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -732,6 +817,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm87_group);
+	sysfs_remove_group(&client->dev.kobj, &lm87_group_opt);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index d9eeaf7..6882ce7 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1,7 +1,7 @@
 /*
  * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2006  Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm83 driver. The LM90 is a sensor chip made by National
  * Semiconductor. It reports up to two temperatures (its own plus up to
@@ -79,6 +79,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -327,6 +328,16 @@
 	return sprintf(buf, "%d\n", data->alarms);
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute
+			  *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm90_data *data = lm90_update_device(dev);
+	int bitnr = attr->index;
+
+	return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
+}
+
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8,
@@ -344,8 +355,45 @@
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
 	set_temphyst, 3);
 static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
+
+/* Individual alarm files */
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+/* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *lm90_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group lm90_group = {
+	.attrs = lm90_attributes,
+};
+
 /* pec used for ADM1032 only */
 static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
 			char *buf)
@@ -569,39 +617,25 @@
 	lm90_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group)))
+		goto exit_detach;
+	if (new_client->flags & I2C_CLIENT_PEC) {
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_pec)))
+			goto exit_remove_files;
+	}
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_input.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_input.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_min.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_min.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_max.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_max.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_crit.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_crit.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_crit_hyst.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_crit_hyst.dev_attr);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
-	if (new_client->flags & I2C_CLIENT_PEC)
-		device_create_file(&new_client->dev, &dev_attr_pec);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &lm90_group);
+	device_remove_file(&new_client->dev, &dev_attr_pec);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -634,6 +668,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm90_group);
+	device_remove_file(&client->dev, &dev_attr_pec);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 197f772..30b5363 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -288,6 +288,23 @@
 	return 1;
 }
 
+static struct attribute *lm92_attributes[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_crit.attr,
+	&dev_attr_temp1_crit_hyst.attr,
+	&dev_attr_temp1_min.attr,
+	&dev_attr_temp1_min_hyst.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	&dev_attr_alarms.attr,
+
+	NULL
+};
+
+static const struct attribute_group lm92_group = {
+	.attrs = lm92_attributes,
+};
+
 /* The following function does more than just detection. If detection
    succeeds, it also registers the new chip. */
 static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -359,23 +376,19 @@
 	lm92_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
 	return 0;
 
+exit_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &lm92_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -397,6 +410,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm92_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index b4135b5..2f58f65 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -34,6 +34,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
 					0x29, 0x2a, 0x2b,
@@ -172,6 +173,22 @@
 	set_temp_hyst2);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *max1619_attributes[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp2_min.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp2_crit.attr,
+	&dev_attr_temp2_crit_hyst.attr,
+
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group max1619_group = {
+	.attrs = max1619_attributes,
+};
+
 /*
  * Real code
  */
@@ -273,22 +290,19 @@
 	max1619_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &max1619_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -318,6 +332,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &max1619_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 236f9f2..3b8b819 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -328,6 +328,12 @@
 	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
 };
 
+#define FAN_UNIT_ATTRS(X)	\
+	&fan_input[X].dev_attr.attr,	\
+	&fan_status[X].dev_attr.attr,	\
+	&fan_div[X].dev_attr.attr,	\
+	&fan_min[X].dev_attr.attr
+
 static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -360,6 +366,19 @@
 	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
 };
 
+static struct attribute * pc8736x_fan_attr_array[] = {
+	FAN_UNIT_ATTRS(0),
+	FAN_UNIT_ATTRS(1),
+	FAN_UNIT_ATTRS(2),
+	&pwm[0].dev_attr.attr,
+	&pwm[1].dev_attr.attr,
+	&pwm[2].dev_attr.attr,
+	NULL
+};
+static const struct attribute_group pc8736x_fan_group = {
+	.attrs = pc8736x_fan_attr_array,
+};
+
 static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -472,6 +491,61 @@
 	SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
 };
 
+#define VIN_UNIT_ATTRS(X) \
+	&in_input[X].dev_attr.attr,	\
+	&in_status[X].dev_attr.attr,	\
+	&in_min[X].dev_attr.attr,	\
+	&in_max[X].dev_attr.attr
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", data->vrm);
+}
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	data->vrm = simple_strtoul(buf, NULL, 10);
+	return count;
+}
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
+
+static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", data->in_alarms);
+}
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+
+static struct attribute *pc8736x_vin_attr_array[] = {
+	VIN_UNIT_ATTRS(0),
+	VIN_UNIT_ATTRS(1),
+	VIN_UNIT_ATTRS(2),
+	VIN_UNIT_ATTRS(3),
+	VIN_UNIT_ATTRS(4),
+	VIN_UNIT_ATTRS(5),
+	VIN_UNIT_ATTRS(6),
+	VIN_UNIT_ATTRS(7),
+	VIN_UNIT_ATTRS(8),
+	VIN_UNIT_ATTRS(9),
+	VIN_UNIT_ATTRS(10),
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	&dev_attr_alarms_in.attr,
+	NULL
+};
+static const struct attribute_group pc8736x_vin_group = {
+	.attrs = pc8736x_vin_attr_array,
+};
+
 static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -590,33 +664,22 @@
 		    show_therm_crit, set_therm_crit, 2+11),
 };
 
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pc87360_data *data = pc87360_update_device(dev);
-	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
-}
-static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+#define THERM_UNIT_ATTRS(X) \
+	&therm_input[X].dev_attr.attr,	\
+	&therm_status[X].dev_attr.attr,	\
+	&therm_min[X].dev_attr.attr,	\
+	&therm_max[X].dev_attr.attr,	\
+	&therm_crit[X].dev_attr.attr
 
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pc87360_data *data = pc87360_update_device(dev);
-	return sprintf(buf, "%u\n", data->vrm);
-}
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
-	data->vrm = simple_strtoul(buf, NULL, 10);
-	return count;
-}
-static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
-
-static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pc87360_data *data = pc87360_update_device(dev);
-	return sprintf(buf, "%u\n", data->in_alarms);
-}
-static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+static struct attribute * pc8736x_therm_attr_array[] = {
+	THERM_UNIT_ATTRS(0),
+	THERM_UNIT_ATTRS(1),
+	THERM_UNIT_ATTRS(2),
+	NULL
+};
+static const struct attribute_group pc8736x_therm_group = {
+	.attrs = pc8736x_therm_attr_array,
+};
 
 static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
@@ -736,6 +799,25 @@
 }
 static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
 
+#define TEMP_UNIT_ATTRS(X) \
+	&temp_input[X].dev_attr.attr,	\
+	&temp_status[X].dev_attr.attr,	\
+	&temp_min[X].dev_attr.attr,	\
+	&temp_max[X].dev_attr.attr,	\
+	&temp_crit[X].dev_attr.attr
+
+static struct attribute * pc8736x_temp_attr_array[] = {
+	TEMP_UNIT_ATTRS(0),
+	TEMP_UNIT_ATTRS(1),
+	TEMP_UNIT_ATTRS(2),
+	/* include the few miscellaneous atts here */
+	&dev_attr_alarms_temp.attr,
+	NULL
+};
+static const struct attribute_group pc8736x_temp_group = {
+	.attrs = pc8736x_temp_attr_array,
+};
+
 /*
  * Device detection, registration and update
  */
@@ -936,60 +1018,69 @@
 		pc87360_init_client(client, use_thermistors);
 	}
 
-	/* Register sysfs hooks */
+	/* Register all-or-nothing sysfs groups */
+
+	if (data->innr &&
+	    (err = sysfs_create_group(&client->dev.kobj,
+				      &pc8736x_vin_group)))
+		goto ERROR3;
+
+	if (data->innr == 14 &&
+	    (err = sysfs_create_group(&client->dev.kobj,
+				      &pc8736x_therm_group)))
+		goto ERROR3;
+
+	/* create device attr-files for varying sysfs groups */
+
+	if (data->tempnr) {
+		for (i = 0; i < data->tempnr; i++) {
+			if ((err = device_create_file(dev,
+					&temp_input[i].dev_attr))
+			    || (err = device_create_file(dev,
+					&temp_min[i].dev_attr))
+			    || (err = device_create_file(dev,
+					&temp_max[i].dev_attr))
+			    || (err = device_create_file(dev,
+					&temp_crit[i].dev_attr))
+			    || (err = device_create_file(dev,
+					&temp_status[i].dev_attr)))
+				goto ERROR3;
+		}
+		if ((err = device_create_file(dev, &dev_attr_alarms_temp)))
+			goto ERROR3;
+	}
+
+	for (i = 0; i < data->fannr; i++) {
+		if (FAN_CONFIG_MONITOR(data->fan_conf, i)
+		    && ((err = device_create_file(dev,
+					&fan_input[i].dev_attr))
+			|| (err = device_create_file(dev,
+					&fan_min[i].dev_attr))
+			|| (err = device_create_file(dev,
+					&fan_div[i].dev_attr))
+			|| (err = device_create_file(dev,
+					&fan_status[i].dev_attr))))
+			goto ERROR3;
+
+		if (FAN_CONFIG_CONTROL(data->fan_conf, i)
+		    && (err = device_create_file(dev, &pwm[i].dev_attr)))
+			goto ERROR3;
+	}
+
 	data->class_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto ERROR3;
 	}
-
-	if (data->innr) {
-		for (i = 0; i < 11; i++) {
-			device_create_file(dev, &in_input[i].dev_attr);
-			device_create_file(dev, &in_min[i].dev_attr);
-			device_create_file(dev, &in_max[i].dev_attr);
-			device_create_file(dev, &in_status[i].dev_attr);
-		}
-		device_create_file(dev, &dev_attr_cpu0_vid);
-		device_create_file(dev, &dev_attr_vrm);
-		device_create_file(dev, &dev_attr_alarms_in);
-	}
-
-	if (data->tempnr) {
-		for (i = 0; i < data->tempnr; i++) {
-			device_create_file(dev, &temp_input[i].dev_attr);
-			device_create_file(dev, &temp_min[i].dev_attr);
-			device_create_file(dev, &temp_max[i].dev_attr);
-			device_create_file(dev, &temp_crit[i].dev_attr);
-			device_create_file(dev, &temp_status[i].dev_attr);
-		}
-		device_create_file(dev, &dev_attr_alarms_temp);
-	}
-
-	if (data->innr == 14) {
-		for (i = 0; i < 3; i++) {
-			device_create_file(dev, &therm_input[i].dev_attr);
-			device_create_file(dev, &therm_min[i].dev_attr);
-			device_create_file(dev, &therm_max[i].dev_attr);
-			device_create_file(dev, &therm_crit[i].dev_attr);
-			device_create_file(dev, &therm_status[i].dev_attr);
-		}
-	}
-
-	for (i = 0; i < data->fannr; i++) {
-		if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
-			device_create_file(dev, &fan_input[i].dev_attr);
-			device_create_file(dev, &fan_min[i].dev_attr);
-			device_create_file(dev, &fan_div[i].dev_attr);
-			device_create_file(dev, &fan_status[i].dev_attr);
-		}
-		if (FAN_CONFIG_CONTROL(data->fan_conf, i))
-			device_create_file(dev, &pwm[i].dev_attr);
-	}
-
 	return 0;
 
 ERROR3:
+	/* can still remove groups whose members were added individually */
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
+
 	i2c_detach_client(client);
 ERROR2:
 	for (i = 0; i < 3; i++) {
@@ -1009,6 +1100,11 @@
 
 	hwmon_device_unregister(data->class_dev);
 
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
+
 	if ((i = i2c_detach_client(client)))
 		return i;
 
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 3783af4..95a4b5d 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -61,6 +61,7 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 
@@ -473,6 +474,50 @@
 	return sprintf(buf, "%d\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static struct attribute *sis5595_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in3_max.attr,
+
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan2_div.attr,
+
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group sis5595_group = {
+	.attrs = sis5595_attributes,
+};
+
+static struct attribute *sis5595_attributes_opt[] = {
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	NULL
+};
+
+static const struct attribute_group sis5595_group_opt = {
+	.attrs = sis5595_attributes_opt,
+};
  
 /* This is called when the module is loaded */
 static int sis5595_detect(struct i2c_adapter *adapter)
@@ -566,43 +611,37 @@
 	}
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &sis5595_group)))
+		goto exit_detach;
+	if (data->maxins == 4) {
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_in4_input))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_in4_min))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_in4_max)))
+			goto exit_remove_files;
+	} else {
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_temp1_input))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_temp1_max))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_temp1_max_hyst)))
+			goto exit_remove_files;
+	}
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	if (data->maxins == 4) {
-		device_create_file(&new_client->dev, &dev_attr_in4_input);
-		device_create_file(&new_client->dev, &dev_attr_in4_min);
-		device_create_file(&new_client->dev, &dev_attr_in4_max);
-	}
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-	if (data->maxins == 3) {
-		device_create_file(&new_client->dev, &dev_attr_temp1_input);
-		device_create_file(&new_client->dev, &dev_attr_temp1_max);
-		device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	}
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &sis5595_group);
+	sysfs_remove_group(&new_client->dev.kobj, &sis5595_group_opt);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -619,6 +658,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &sis5595_group);
+	sysfs_remove_group(&client->dev.kobj, &sis5595_group_opt);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index a858693..72b0e2d8 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -176,9 +176,6 @@
 sysfs_temp(3);
 sysfs_temp(4);
 
-#define device_create_file_temp(client, num) \
-	device_create_file(&client->dev, &dev_attr_temp##num##_input)
-
 /* FAN: 1 RPM/bit
    REG: count of 90kHz pulses / revolution */
 static int fan_from_reg(u16 reg)
@@ -205,8 +202,22 @@
 sysfs_fan(3);
 sysfs_fan(4);
 
-#define device_create_file_fan(client, num) \
-	device_create_file(&client->dev, &dev_attr_fan##num##_input)
+static struct attribute *smsc47b397_attributes[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp4_input.attr,
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan3_input.attr,
+	&dev_attr_fan4_input.attr,
+
+	NULL
+};
+
+static const struct attribute_group smsc47b397_group = {
+	.attrs = smsc47b397_attributes,
+};
 
 static int smsc47b397_detach_client(struct i2c_client *client)
 {
@@ -214,6 +225,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &smsc47b397_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
@@ -268,24 +280,19 @@
 	if ((err = i2c_attach_client(new_client)))
 		goto error_free;
 
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &smsc47b397_group)))
+		goto error_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto error_detach;
+		goto error_remove;
 	}
 
-	device_create_file_temp(new_client, 1);
-	device_create_file_temp(new_client, 2);
-	device_create_file_temp(new_client, 3);
-	device_create_file_temp(new_client, 4);
-
-	device_create_file_fan(new_client, 1);
-	device_create_file_fan(new_client, 2);
-	device_create_file_fan(new_client, 3);
-	device_create_file_fan(new_client, 4);
-
 	return 0;
 
+error_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &smsc47b397_group);
 error_detach:
 	i2c_detach_client(new_client);
 error_free:
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 6c81b84..47132fd 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -35,6 +35,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 /* Address is autodetected, there is no default value */
@@ -347,6 +348,30 @@
 
 static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
 
+/* Almost all sysfs files may or may not be created depending on the chip
+   setup so we create them individually. It is still convenient to define a
+   group to remove them all at once. */
+static struct attribute *smsc47m1_attributes[] = {
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan2_div.attr,
+
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm1_enable.attr,
+	&dev_attr_pwm2.attr,
+	&dev_attr_pwm2_enable.attr,
+
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group smsc47m1_group = {
+	.attrs = smsc47m1_attributes,
+};
+
 static int __init smsc47m1_find(unsigned short *addr)
 {
 	u8 val;
@@ -429,7 +454,8 @@
 	pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
 	       == 0x04;
 	if (!(fan1 || fan2 || pwm1 || pwm2)) {
-		dev_warn(&new_client->dev, "Device is not configured, will not use\n");
+		dev_warn(&adapter->dev, "Device at 0x%x is not configured, "
+			 "will not use\n", new_client->addr);
 		err = -ENODEV;
 		goto error_free;
 	}
@@ -446,46 +472,62 @@
 	smsc47m1_update_device(&new_client->dev, 1);
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
-		goto error_detach;
-	}
-
 	if (fan1) {
-		device_create_file(&new_client->dev, &dev_attr_fan1_input);
-		device_create_file(&new_client->dev, &dev_attr_fan1_min);
-		device_create_file(&new_client->dev, &dev_attr_fan1_div);
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_fan1_input))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_fan1_min))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_fan1_div)))
+			goto error_remove_files;
 	} else
 		dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, "
 			"skipping\n");
 
 	if (fan2) {
-		device_create_file(&new_client->dev, &dev_attr_fan2_input);
-		device_create_file(&new_client->dev, &dev_attr_fan2_min);
-		device_create_file(&new_client->dev, &dev_attr_fan2_div);
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_fan2_input))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_fan2_min))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_fan2_div)))
+			goto error_remove_files;
 	} else
 		dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
 			"skipping\n");
 
 	if (pwm1) {
-		device_create_file(&new_client->dev, &dev_attr_pwm1);
-		device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_pwm1))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_pwm1_enable)))
+			goto error_remove_files;
 	} else
 		dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
 			"skipping\n");
 	if (pwm2) {
-		device_create_file(&new_client->dev, &dev_attr_pwm2);
-		device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_pwm2))
+		 || (err = device_create_file(&new_client->dev,
+					      &dev_attr_pwm2_enable)))
+			goto error_remove_files;
 	} else
 		dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
 			"skipping\n");
 
-	device_create_file(&new_client->dev, &dev_attr_alarms);
+	if ((err = device_create_file(&new_client->dev, &dev_attr_alarms)))
+		goto error_remove_files;
+
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto error_remove_files;
+	}
 
 	return 0;
 
-error_detach:
+error_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &smsc47m1_group);
 	i2c_detach_client(new_client);
 error_free:
 	kfree(data);
@@ -500,6 +542,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &smsc47m1_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index bdc4570..a6833f4 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -30,6 +30,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
+#include <linux/sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
@@ -370,6 +371,75 @@
 static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400);
 static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800);
 
+static struct attribute *smsc47m192_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in0_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in3_alarm.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in5_alarm.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in6_alarm.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in7_min.dev_attr.attr,
+	&sensor_dev_attr_in7_max.dev_attr.attr,
+	&sensor_dev_attr_in7_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_offset.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_offset.dev_attr.attr,
+	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp3_input_fault.dev_attr.attr,
+
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	NULL
+};
+
+static const struct attribute_group smsc47m192_group = {
+	.attrs = smsc47m192_attributes,
+};
+
+static struct attribute *smsc47m192_attributes_in4[] = {
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in4_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group smsc47m192_group_in4 = {
+	.attrs = smsc47m192_attributes_in4,
+};
+
 /* This function is called when:
     * smsc47m192_driver is inserted (when this module is loaded), for each
       available adapter
@@ -471,80 +541,28 @@
 	smsc47m192_init_client(client);
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
+	if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group)))
 		goto exit_detach;
-	}
-
-	device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr);
 
 	/* Pin 110 is either in4 (+12V) or VID4 */
 	config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
 	if (!(config & 0x20)) {
-		device_create_file(&client->dev,
-				   &sensor_dev_attr_in4_input.dev_attr);
-		device_create_file(&client->dev,
-				   &sensor_dev_attr_in4_min.dev_attr);
-		device_create_file(&client->dev,
-				   &sensor_dev_attr_in4_max.dev_attr);
-		device_create_file(&client->dev,
-				   &sensor_dev_attr_in4_alarm.dev_attr);
+		if ((err = sysfs_create_group(&client->dev.kobj,
+					      &smsc47m192_group_in4)))
+			goto exit_remove_files;
 	}
-	device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr);
-	device_create_file(&client->dev,
-			   &sensor_dev_attr_temp1_offset.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr);
-	device_create_file(&client->dev,
-			   &sensor_dev_attr_temp2_offset.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr);
-	device_create_file(&client->dev,
-			   &sensor_dev_attr_temp2_input_fault.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr);
-	device_create_file(&client->dev,
-			   &sensor_dev_attr_temp3_offset.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr);
-	device_create_file(&client->dev,
-			   &sensor_dev_attr_temp3_input_fault.dev_attr);
-	device_create_file(&client->dev, &dev_attr_cpu0_vid);
-	device_create_file(&client->dev, &dev_attr_vrm);
+
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove_files;
+	}
 
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
+	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
 exit_detach:
 	i2c_detach_client(client);
 exit_free:
@@ -559,6 +577,8 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
+	sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 95ae056..f8acada 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -40,6 +40,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 
@@ -570,6 +571,48 @@
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *via686a_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in4_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_in4_max.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp3_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	&dev_attr_temp2_max_hyst.attr,
+	&dev_attr_temp3_max_hyst.attr,
+
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_div.attr,
+
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group via686a_group = {
+	.attrs = via686a_attributes,
+};
+
 /* The driver. I choose to use type i2c_driver, as at is identical to both
    smbus_driver and isa_driver, and clients could be of either kind */
 static struct i2c_driver via686a_driver = {
@@ -650,46 +693,19 @@
 	via686a_init_client(new_client);
 
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &via686a_group)))
+		goto exit_detach;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove_files;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp3_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp3_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp3_max_hyst);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_alarms);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &via686a_group);
 exit_detach:
 	i2c_detach_client(new_client);
 exit_free:
@@ -705,6 +721,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &via686a_group);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
new file mode 100644
index 0000000..25cc560
--- /dev/null
+++ b/drivers/hwmon/vt1211.c
@@ -0,0 +1,1355 @@
+/*
+ * vt1211.c - driver for the VIA VT1211 Super-I/O chip integrated hardware
+ *            monitoring features
+ * Copyright (C) 2006 Juerg Haefliger <juergh@gmail.com>
+ *
+ * This driver is based on the driver for kernel 2.4 by Mark D. Studebaker
+ * and its port to kernel 2.6 by Lars Ekman.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <asm/io.h>
+
+static int uch_config = -1;
+module_param(uch_config, int, 0);
+MODULE_PARM_DESC(uch_config, "Initialize the universal channel configuration");
+
+static int int_mode = -1;
+module_param(int_mode, int, 0);
+MODULE_PARM_DESC(int_mode, "Force the temperature interrupt mode");
+
+static struct platform_device *pdev;
+
+#define DRVNAME "vt1211"
+
+/* ---------------------------------------------------------------------
+ * Registers
+ *
+ * The sensors are defined as follows.
+ *
+ * Sensor          Voltage Mode   Temp Mode   Notes (from the datasheet)
+ * --------        ------------   ---------   --------------------------
+ * Reading 1                      temp1       Intel thermal diode
+ * Reading 3                      temp2       Internal thermal diode
+ * UCH1/Reading2   in0            temp3       NTC type thermistor
+ * UCH2            in1            temp4       +2.5V
+ * UCH3            in2            temp5       VccP
+ * UCH4            in3            temp6       +5V
+ * UCH5            in4            temp7       +12V
+ * 3.3V            in5                        Internal VDD (+3.3V)
+ *
+ * --------------------------------------------------------------------- */
+
+/* Voltages (in) numbered 0-5 (ix) */
+#define VT1211_REG_IN(ix)		(0x21 + (ix))
+#define VT1211_REG_IN_MIN(ix)		((ix) == 0 ? 0x3e : 0x2a + 2 * (ix))
+#define VT1211_REG_IN_MAX(ix)		((ix) == 0 ? 0x3d : 0x29 + 2 * (ix))
+
+/* Temperatures (temp) numbered 0-6 (ix) */
+static u8 regtemp[]	= {0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25};
+static u8 regtempmax[]	= {0x39, 0x1d, 0x3d, 0x2b, 0x2d, 0x2f, 0x31};
+static u8 regtemphyst[]	= {0x3a, 0x1e, 0x3e, 0x2c, 0x2e, 0x30, 0x32};
+
+/* Fans numbered 0-1 (ix) */
+#define VT1211_REG_FAN(ix)		(0x29 + (ix))
+#define VT1211_REG_FAN_MIN(ix)		(0x3b + (ix))
+#define VT1211_REG_FAN_DIV		 0x47
+
+/* PWMs numbered 0-1 (ix) */
+/* Auto points numbered 0-3 (ap) */
+#define VT1211_REG_PWM(ix)		(0x60 + (ix))
+#define VT1211_REG_PWM_CLK		 0x50
+#define VT1211_REG_PWM_CTL		 0x51
+#define VT1211_REG_PWM_AUTO_TEMP(ap)	(0x55 - (ap))
+#define VT1211_REG_PWM_AUTO_PWM(ix, ap)	(0x58 + 2 * (ix) - (ap))
+
+/* Miscellaneous registers */
+#define VT1211_REG_CONFIG		0x40
+#define VT1211_REG_ALARM1		0x41
+#define VT1211_REG_ALARM2		0x42
+#define VT1211_REG_VID			0x45
+#define VT1211_REG_UCH_CONFIG		0x4a
+#define VT1211_REG_TEMP1_CONFIG		0x4b
+#define VT1211_REG_TEMP2_CONFIG		0x4c
+
+/* In, temp & fan alarm bits */
+static const u8 bitalarmin[]	= {11, 0, 1, 3, 8, 2, 9};
+static const u8 bitalarmtemp[]	= {4, 15, 11, 0, 1, 3, 8};
+static const u8 bitalarmfan[]	= {6, 7};
+
+/* ---------------------------------------------------------------------
+ * Data structures and manipulation thereof
+ * --------------------------------------------------------------------- */
+
+struct vt1211_data {
+	unsigned short addr;
+	const char *name;
+	struct class_device *class_dev;
+
+	struct mutex update_lock;
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* Register values */
+	u8  in[6];
+	u8  in_max[6];
+	u8  in_min[6];
+	u8  temp[7];
+	u8  temp_max[7];
+	u8  temp_hyst[7];
+	u8  fan[2];
+	u8  fan_min[2];
+	u8  fan_div[2];
+	u8  fan_ctl;
+	u8  pwm[2];
+	u8  pwm_ctl[2];
+	u8  pwm_clk;
+	u8  pwm_auto_temp[4];
+	u8  pwm_auto_pwm[2][4];
+	u8  vid;		/* Read once at init time */
+	u8  vrm;
+	u8  uch_config;		/* Read once at init time */
+	u16 alarms;
+};
+
+/* ix = [0-5] */
+#define ISVOLT(ix, uch_config)	((ix) > 4 ? 1 : \
+				 !(((uch_config) >> ((ix) + 2)) & 1))
+
+/* ix = [0-6] */
+#define ISTEMP(ix, uch_config)	((ix) < 2 ? 1 : \
+				 ((uch_config) >> (ix)) & 1)
+
+/* in5 (ix = 5) is special. It's the internal 3.3V so it's scaled in the
+   driver according to the VT1211 BIOS porting guide */
+#define IN_FROM_REG(ix, reg)	((reg) < 3 ? 0 : (ix) == 5 ? \
+				 (((reg) - 3) * 15882 + 479) / 958 : \
+				 (((reg) - 3) * 10000 + 479) / 958)
+#define IN_TO_REG(ix, val)	(SENSORS_LIMIT((ix) == 5 ? \
+				 ((val) * 958 + 7941) / 15882 + 3 : \
+				 ((val) * 958 + 5000) / 10000 + 3, 0, 255))
+
+/* temp1 (ix = 0) is an intel thermal diode which is scaled in user space.
+   temp2 (ix = 1) is the internal temp diode so it's scaled in the driver
+   according to some measurements that I took on an EPIA M10000.
+   temp3-7 are thermistor based so the driver returns the voltage measured at
+   the pin (range 0V - 2.2V). */
+#define TEMP_FROM_REG(ix, reg)	((ix) == 0 ? (reg) * 1000 : \
+				 (ix) == 1 ? (reg) < 51 ? 0 : \
+				 ((reg) - 51) * 1000 : \
+				 ((253 - (reg)) * 2200 + 105) / 210)
+#define TEMP_TO_REG(ix, val)	SENSORS_LIMIT( \
+				 ((ix) == 0 ? ((val) + 500) / 1000 : \
+				  (ix) == 1 ? ((val) + 500) / 1000 + 51 : \
+				  253 - ((val) * 210 + 1100) / 2200), 0, 255)
+
+#define DIV_FROM_REG(reg)	(1 << (reg))
+
+#define RPM_FROM_REG(reg, div)	(((reg) == 0) || ((reg) == 255) ? 0 : \
+				 1310720 / (reg) / DIV_FROM_REG(div))
+#define RPM_TO_REG(val, div)	((val) == 0 ? 255 : \
+				 SENSORS_LIMIT((1310720 / (val) / \
+				 DIV_FROM_REG(div)), 1, 254))
+
+/* ---------------------------------------------------------------------
+ * Super-I/O constants and functions
+ * --------------------------------------------------------------------- */
+
+/* Configuration & data index port registers */
+#define SIO_REG_CIP		0x2e
+#define SIO_REG_DIP		0x2f
+
+/* Configuration registers */
+#define SIO_VT1211_LDN		0x07	/* logical device number */
+#define SIO_VT1211_DEVID	0x20	/* device ID */
+#define SIO_VT1211_DEVREV	0x21	/* device revision */
+#define SIO_VT1211_ACTIVE	0x30	/* HW monitor active */
+#define SIO_VT1211_BADDR	0x60	/* base I/O address */
+#define SIO_VT1211_ID		0x3c	/* VT1211 device ID */
+
+/* VT1211 logical device numbers */
+#define SIO_VT1211_LDN_HWMON	0x0b	/* HW monitor */
+
+static inline void superio_outb(int reg, int val)
+{
+	outb(reg, SIO_REG_CIP);
+	outb(val, SIO_REG_DIP);
+}
+
+static inline int superio_inb(int reg)
+{
+	outb(reg, SIO_REG_CIP);
+	return inb(SIO_REG_DIP);
+}
+
+static inline void superio_select(int ldn)
+{
+	outb(SIO_VT1211_LDN, SIO_REG_CIP);
+	outb(ldn, SIO_REG_DIP);
+}
+
+static inline void superio_enter(void)
+{
+	outb(0x87, SIO_REG_CIP);
+	outb(0x87, SIO_REG_CIP);
+}
+
+static inline void superio_exit(void)
+{
+	outb(0xaa, SIO_REG_CIP);
+}
+
+/* ---------------------------------------------------------------------
+ * Device I/O access
+ * --------------------------------------------------------------------- */
+
+static inline u8 vt1211_read8(struct vt1211_data *data, u8 reg)
+{
+	return inb(data->addr + reg);
+}
+
+static inline void vt1211_write8(struct vt1211_data *data, u8 reg, u8 val)
+{
+	outb(val, data->addr + reg);
+}
+
+static struct vt1211_data *vt1211_update_device(struct device *dev)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	int ix, val;
+
+	mutex_lock(&data->update_lock);
+
+	/* registers cache is refreshed after 1 second */
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		/* read VID */
+		data->vid = vt1211_read8(data, VT1211_REG_VID) & 0x1f;
+
+		/* voltage (in) registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
+			if (ISVOLT(ix, data->uch_config)) {
+				data->in[ix] = vt1211_read8(data,
+						VT1211_REG_IN(ix));
+				data->in_min[ix] = vt1211_read8(data,
+						VT1211_REG_IN_MIN(ix));
+				data->in_max[ix] = vt1211_read8(data,
+						VT1211_REG_IN_MAX(ix));
+			}
+		}
+
+		/* temp registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) {
+			if (ISTEMP(ix, data->uch_config)) {
+				data->temp[ix] = vt1211_read8(data,
+						regtemp[ix]);
+				data->temp_max[ix] = vt1211_read8(data,
+						regtempmax[ix]);
+				data->temp_hyst[ix] = vt1211_read8(data,
+						regtemphyst[ix]);
+			}
+		}
+
+		/* fan & pwm registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) {
+			data->fan[ix] = vt1211_read8(data,
+						VT1211_REG_FAN(ix));
+			data->fan_min[ix] = vt1211_read8(data,
+						VT1211_REG_FAN_MIN(ix));
+			data->pwm[ix] = vt1211_read8(data,
+						VT1211_REG_PWM(ix));
+		}
+		val = vt1211_read8(data, VT1211_REG_FAN_DIV);
+		data->fan_div[0] = (val >> 4) & 3;
+		data->fan_div[1] = (val >> 6) & 3;
+		data->fan_ctl = val & 0xf;
+
+		val = vt1211_read8(data, VT1211_REG_PWM_CTL);
+		data->pwm_ctl[0] = val & 0xf;
+		data->pwm_ctl[1] = (val >> 4) & 0xf;
+
+		data->pwm_clk = vt1211_read8(data, VT1211_REG_PWM_CLK);
+
+		/* pwm & temp auto point registers */
+		data->pwm_auto_pwm[0][1] = vt1211_read8(data,
+						VT1211_REG_PWM_AUTO_PWM(0, 1));
+		data->pwm_auto_pwm[0][2] = vt1211_read8(data,
+						VT1211_REG_PWM_AUTO_PWM(0, 2));
+		data->pwm_auto_pwm[1][1] = vt1211_read8(data,
+						VT1211_REG_PWM_AUTO_PWM(1, 1));
+		data->pwm_auto_pwm[1][2] = vt1211_read8(data,
+						VT1211_REG_PWM_AUTO_PWM(1, 2));
+		for (ix = 0; ix < ARRAY_SIZE(data->pwm_auto_temp); ix++) {
+			data->pwm_auto_temp[ix] = vt1211_read8(data,
+						VT1211_REG_PWM_AUTO_TEMP(ix));
+		}
+
+		/* alarm registers */
+		data->alarms = (vt1211_read8(data, VT1211_REG_ALARM2) << 8) |
+				vt1211_read8(data, VT1211_REG_ALARM1);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/* ---------------------------------------------------------------------
+ * Voltage sysfs interfaces
+ * ix = [0-5]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_IN_INPUT	0
+#define SHOW_SET_IN_MIN	1
+#define SHOW_SET_IN_MAX	2
+#define SHOW_IN_ALARM	3
+
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct vt1211_data *data = vt1211_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SHOW_IN_INPUT:
+		res = IN_FROM_REG(ix, data->in[ix]);
+		break;
+	case SHOW_SET_IN_MIN:
+		res = IN_FROM_REG(ix, data->in_min[ix]);
+		break;
+	case SHOW_SET_IN_MAX:
+		res = IN_FROM_REG(ix, data->in_max[ix]);
+		break;
+	case SHOW_IN_ALARM:
+		res = (data->alarms >> bitalarmin[ix]) & 1;
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_in(struct device *dev, struct device_attribute *attr,
+		      const char *buf, size_t count)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	switch (fn) {
+	case SHOW_SET_IN_MIN:
+		data->in_min[ix] = IN_TO_REG(ix, val);
+		vt1211_write8(data, VT1211_REG_IN_MIN(ix), data->in_min[ix]);
+		break;
+	case SHOW_SET_IN_MAX:
+		data->in_max[ix] = IN_TO_REG(ix, val);
+		vt1211_write8(data, VT1211_REG_IN_MAX(ix), data->in_max[ix]);
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Temperature sysfs interfaces
+ * ix = [0-6]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_TEMP_INPUT		0
+#define SHOW_SET_TEMP_MAX	1
+#define SHOW_SET_TEMP_MAX_HYST	2
+#define SHOW_TEMP_ALARM		3
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct vt1211_data *data = vt1211_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SHOW_TEMP_INPUT:
+		res = TEMP_FROM_REG(ix, data->temp[ix]);
+		break;
+	case SHOW_SET_TEMP_MAX:
+		res = TEMP_FROM_REG(ix, data->temp_max[ix]);
+		break;
+	case SHOW_SET_TEMP_MAX_HYST:
+		res = TEMP_FROM_REG(ix, data->temp_hyst[ix]);
+		break;
+	case SHOW_TEMP_ALARM:
+		res = (data->alarms >> bitalarmtemp[ix]) & 1;
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	switch (fn) {
+	case SHOW_SET_TEMP_MAX:
+		data->temp_max[ix] = TEMP_TO_REG(ix, val);
+		vt1211_write8(data, regtempmax[ix],
+			      data->temp_max[ix]);
+		break;
+	case SHOW_SET_TEMP_MAX_HYST:
+		data->temp_hyst[ix] = TEMP_TO_REG(ix, val);
+		vt1211_write8(data, regtemphyst[ix],
+			      data->temp_hyst[ix]);
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Fan sysfs interfaces
+ * ix = [0-1]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_FAN_INPUT		0
+#define SHOW_SET_FAN_MIN	1
+#define SHOW_SET_FAN_DIV	2
+#define SHOW_FAN_ALARM		3
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct vt1211_data *data = vt1211_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SHOW_FAN_INPUT:
+		res = RPM_FROM_REG(data->fan[ix], data->fan_div[ix]);
+		break;
+	case SHOW_SET_FAN_MIN:
+		res = RPM_FROM_REG(data->fan_min[ix], data->fan_div[ix]);
+		break;
+	case SHOW_SET_FAN_DIV:
+		res = DIV_FROM_REG(data->fan_div[ix]);
+		break;
+	case SHOW_FAN_ALARM:
+		res = (data->alarms >> bitalarmfan[ix]) & 1;
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+	int reg;
+
+	mutex_lock(&data->update_lock);
+
+	/* sync the data cache */
+	reg = vt1211_read8(data, VT1211_REG_FAN_DIV);
+	data->fan_div[0] = (reg >> 4) & 3;
+	data->fan_div[1] = (reg >> 6) & 3;
+	data->fan_ctl = reg & 0xf;
+
+	switch (fn) {
+	case SHOW_SET_FAN_MIN:
+		data->fan_min[ix] = RPM_TO_REG(val, data->fan_div[ix]);
+		vt1211_write8(data, VT1211_REG_FAN_MIN(ix),
+			      data->fan_min[ix]);
+		break;
+	case SHOW_SET_FAN_DIV:
+		switch (val) {
+			case 1: data->fan_div[ix] = 0; break;
+			case 2: data->fan_div[ix] = 1; break;
+			case 4: data->fan_div[ix] = 2; break;
+			case 8: data->fan_div[ix] = 3; break;
+			default:
+				count = -EINVAL;
+				dev_warn(dev, "fan div value %ld not "
+					 "supported. Choose one of 1, 2, "
+					 "4, or 8.\n", val);
+				goto EXIT;
+		}
+		vt1211_write8(data, VT1211_REG_FAN_DIV,
+			      ((data->fan_div[1] << 6) |
+			       (data->fan_div[0] << 4) |
+				data->fan_ctl));
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+EXIT:
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * PWM sysfs interfaces
+ * ix = [0-1]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_PWM			0
+#define SHOW_SET_PWM_ENABLE		1
+#define SHOW_SET_PWM_FREQ		2
+#define SHOW_SET_PWM_AUTO_CHANNELS_TEMP	3
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct vt1211_data *data = vt1211_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SHOW_PWM:
+		res = data->pwm[ix];
+		break;
+	case SHOW_SET_PWM_ENABLE:
+		res = ((data->pwm_ctl[ix] >> 3) & 1) ? 2 : 0;
+		break;
+	case SHOW_SET_PWM_FREQ:
+		res = 90000 >> (data->pwm_clk & 7);
+		break;
+	case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:
+		res = (data->pwm_ctl[ix] & 7) + 1;
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+	int tmp, reg;
+
+	mutex_lock(&data->update_lock);
+
+	switch (fn) {
+	case SHOW_SET_PWM_ENABLE:
+		/* sync the data cache */
+		reg = vt1211_read8(data, VT1211_REG_FAN_DIV);
+		data->fan_div[0] = (reg >> 4) & 3;
+		data->fan_div[1] = (reg >> 6) & 3;
+		data->fan_ctl = reg & 0xf;
+		reg = vt1211_read8(data, VT1211_REG_PWM_CTL);
+		data->pwm_ctl[0] = reg & 0xf;
+		data->pwm_ctl[1] = (reg >> 4) & 0xf;
+		switch (val) {
+		case 0:
+			data->pwm_ctl[ix] &= 7;
+			/* disable SmartGuardian if both PWM outputs are
+			 * disabled */
+			if ((data->pwm_ctl[ix ^ 1] & 1) == 0) {
+				data->fan_ctl &= 0xe;
+			}
+			break;
+		case 2:
+			data->pwm_ctl[ix] |= 8;
+			data->fan_ctl |= 1;
+			break;
+		default:
+			count = -EINVAL;
+			dev_warn(dev, "pwm mode %ld not supported. "
+				 "Choose one of 0 or 2.\n", val);
+			goto EXIT;
+		}
+		vt1211_write8(data, VT1211_REG_PWM_CTL,
+			      ((data->pwm_ctl[1] << 4) |
+				data->pwm_ctl[0]));
+		vt1211_write8(data, VT1211_REG_FAN_DIV,
+			      ((data->fan_div[1] << 6) |
+			       (data->fan_div[0] << 4) |
+				data->fan_ctl));
+		break;
+	case SHOW_SET_PWM_FREQ:
+		val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000);
+		/* calculate tmp = log2(val) */
+		tmp = 0;
+		for (val >>= 1; val > 0; val >>= 1) {
+			tmp++;
+		}
+		/* sync the data cache */
+		reg = vt1211_read8(data, VT1211_REG_PWM_CLK);
+		data->pwm_clk = (reg & 0xf8) | tmp;
+		vt1211_write8(data, VT1211_REG_PWM_CLK, data->pwm_clk);
+		break;
+	case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:
+		if ((val < 1) || (val > 7)) {
+			count = -EINVAL;
+			dev_warn(dev, "temp channel %ld not supported. "
+				 "Choose a value between 1 and 7.\n", val);
+			goto EXIT;
+		}
+		if (!ISTEMP(val - 1, data->uch_config)) {
+			count = -EINVAL;
+			dev_warn(dev, "temp channel %ld is not available.\n",
+				 val);
+			goto EXIT;
+		}
+		/* sync the data cache */
+		reg = vt1211_read8(data, VT1211_REG_PWM_CTL);
+		data->pwm_ctl[0] = reg & 0xf;
+		data->pwm_ctl[1] = (reg >> 4) & 0xf;
+		data->pwm_ctl[ix] = (data->pwm_ctl[ix] & 8) | (val - 1);
+		vt1211_write8(data, VT1211_REG_PWM_CTL,
+			      ((data->pwm_ctl[1] << 4) | data->pwm_ctl[0]));
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+EXIT:
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * PWM auto point definitions
+ * ix = [0-1]
+ * ap = [0-3]
+ * --------------------------------------------------------------------- */
+
+/*
+ * pwm[ix+1]_auto_point[ap+1]_temp mapping table:
+ * Note that there is only a single set of temp auto points that controls both
+ * PWM controllers. We still create 2 sets of sysfs files to make it look
+ * more consistent even though they map to the same registers.
+ *
+ * ix ap : description
+ * -------------------
+ * 0  0  : pwm1/2 off temperature        (pwm_auto_temp[0])
+ * 0  1  : pwm1/2 low speed temperature  (pwm_auto_temp[1])
+ * 0  2  : pwm1/2 high speed temperature (pwm_auto_temp[2])
+ * 0  3  : pwm1/2 full speed temperature (pwm_auto_temp[3])
+ * 1  0  : pwm1/2 off temperature        (pwm_auto_temp[0])
+ * 1  1  : pwm1/2 low speed temperature  (pwm_auto_temp[1])
+ * 1  2  : pwm1/2 high speed temperature (pwm_auto_temp[2])
+ * 1  3  : pwm1/2 full speed temperature (pwm_auto_temp[3])
+ */
+
+static ssize_t show_pwm_auto_point_temp(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct vt1211_data *data = vt1211_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int ap = sensor_attr_2->nr;
+
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->pwm_ctl[ix] & 7,
+		       data->pwm_auto_temp[ap]));
+}
+
+static ssize_t set_pwm_auto_point_temp(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int ap = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+	int reg;
+
+	mutex_lock(&data->update_lock);
+
+	/* sync the data cache */
+	reg = vt1211_read8(data, VT1211_REG_PWM_CTL);
+	data->pwm_ctl[0] = reg & 0xf;
+	data->pwm_ctl[1] = (reg >> 4) & 0xf;
+
+	data->pwm_auto_temp[ap] = TEMP_TO_REG(data->pwm_ctl[ix] & 7, val);
+	vt1211_write8(data, VT1211_REG_PWM_AUTO_TEMP(ap),
+		      data->pwm_auto_temp[ap]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/*
+ * pwm[ix+1]_auto_point[ap+1]_pwm mapping table:
+ * Note that the PWM auto points 0 & 3 are hard-wired in the VT1211 and can't
+ * be changed.
+ *
+ * ix ap : description
+ * -------------------
+ * 0  0  : pwm1 off                   (pwm_auto_pwm[0][0], hard-wired to 0)
+ * 0  1  : pwm1 low speed duty cycle  (pwm_auto_pwm[0][1])
+ * 0  2  : pwm1 high speed duty cycle (pwm_auto_pwm[0][2])
+ * 0  3  : pwm1 full speed            (pwm_auto_pwm[0][3], hard-wired to 255)
+ * 1  0  : pwm2 off                   (pwm_auto_pwm[1][0], hard-wired to 0)
+ * 1  1  : pwm2 low speed duty cycle  (pwm_auto_pwm[1][1])
+ * 1  2  : pwm2 high speed duty cycle (pwm_auto_pwm[1][2])
+ * 1  3  : pwm2 full speed            (pwm_auto_pwm[1][3], hard-wired to 255)
+*/
+
+static ssize_t show_pwm_auto_point_pwm(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct vt1211_data *data = vt1211_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int ap = sensor_attr_2->nr;
+
+	return sprintf(buf, "%d\n", data->pwm_auto_pwm[ix][ap]);
+}
+
+static ssize_t set_pwm_auto_point_pwm(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr_2 =
+						to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int ap = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	if ((val < 0) || (val > 255)) {
+		dev_err(dev, "pwm value %ld is out of range. "
+			"Choose a value between 0 and 255." , val);
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->pwm_auto_pwm[ix][ap] = val;
+	vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap),
+		      data->pwm_auto_pwm[ix][ap]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Miscellaneous sysfs interfaces (VRM, VID, name, and (legacy) alarms)
+ * --------------------------------------------------------------------- */
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+	long val = simple_strtol(buf, NULL, 10);
+
+	data->vrm = val;
+
+	return count;
+}
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+static ssize_t show_name(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct vt1211_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+
+static ssize_t show_alarms(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct vt1211_data *data = vt1211_update_device(dev);
+
+	return sprintf(buf, "%d\n", data->alarms);
+}
+
+/* ---------------------------------------------------------------------
+ * Device attribute structs
+ * --------------------------------------------------------------------- */
+
+#define SENSOR_ATTR_IN_INPUT(ix) \
+	SENSOR_ATTR_2(in##ix##_input, S_IRUGO, \
+		show_in, NULL, SHOW_IN_INPUT, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_input[] = {
+	SENSOR_ATTR_IN_INPUT(0),
+	SENSOR_ATTR_IN_INPUT(1),
+	SENSOR_ATTR_IN_INPUT(2),
+	SENSOR_ATTR_IN_INPUT(3),
+	SENSOR_ATTR_IN_INPUT(4),
+	SENSOR_ATTR_IN_INPUT(5),
+};
+
+#define SENSOR_ATTR_IN_MIN(ix) \
+	SENSOR_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \
+		show_in, set_in, SHOW_SET_IN_MIN, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_min[] = {
+	SENSOR_ATTR_IN_MIN(0),
+	SENSOR_ATTR_IN_MIN(1),
+	SENSOR_ATTR_IN_MIN(2),
+	SENSOR_ATTR_IN_MIN(3),
+	SENSOR_ATTR_IN_MIN(4),
+	SENSOR_ATTR_IN_MIN(5),
+};
+
+#define SENSOR_ATTR_IN_MAX(ix) \
+	SENSOR_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \
+		show_in, set_in, SHOW_SET_IN_MAX, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_max[] = {
+	SENSOR_ATTR_IN_MAX(0),
+	SENSOR_ATTR_IN_MAX(1),
+	SENSOR_ATTR_IN_MAX(2),
+	SENSOR_ATTR_IN_MAX(3),
+	SENSOR_ATTR_IN_MAX(4),
+	SENSOR_ATTR_IN_MAX(5),
+};
+
+#define SENSOR_ATTR_IN_ALARM(ix) \
+	SENSOR_ATTR_2(in##ix##_alarm, S_IRUGO, \
+		show_in, NULL, SHOW_IN_ALARM, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_alarm[] = {
+	SENSOR_ATTR_IN_ALARM(0),
+	SENSOR_ATTR_IN_ALARM(1),
+	SENSOR_ATTR_IN_ALARM(2),
+	SENSOR_ATTR_IN_ALARM(3),
+	SENSOR_ATTR_IN_ALARM(4),
+	SENSOR_ATTR_IN_ALARM(5),
+};
+
+#define SENSOR_ATTR_TEMP_INPUT(ix) \
+	SENSOR_ATTR_2(temp##ix##_input, S_IRUGO, \
+		show_temp, NULL, SHOW_TEMP_INPUT, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_input[] = {
+	SENSOR_ATTR_TEMP_INPUT(1),
+	SENSOR_ATTR_TEMP_INPUT(2),
+	SENSOR_ATTR_TEMP_INPUT(3),
+	SENSOR_ATTR_TEMP_INPUT(4),
+	SENSOR_ATTR_TEMP_INPUT(5),
+	SENSOR_ATTR_TEMP_INPUT(6),
+	SENSOR_ATTR_TEMP_INPUT(7),
+};
+
+#define SENSOR_ATTR_TEMP_MAX(ix) \
+	SENSOR_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \
+		show_temp, set_temp, SHOW_SET_TEMP_MAX, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_max[] = {
+	SENSOR_ATTR_TEMP_MAX(1),
+	SENSOR_ATTR_TEMP_MAX(2),
+	SENSOR_ATTR_TEMP_MAX(3),
+	SENSOR_ATTR_TEMP_MAX(4),
+	SENSOR_ATTR_TEMP_MAX(5),
+	SENSOR_ATTR_TEMP_MAX(6),
+	SENSOR_ATTR_TEMP_MAX(7),
+};
+
+#define SENSOR_ATTR_TEMP_MAX_HYST(ix) \
+	SENSOR_ATTR_2(temp##ix##_max_hyst, S_IRUGO | S_IWUSR, \
+		show_temp, set_temp, SHOW_SET_TEMP_MAX_HYST, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_max_hyst[] = {
+	SENSOR_ATTR_TEMP_MAX_HYST(1),
+	SENSOR_ATTR_TEMP_MAX_HYST(2),
+	SENSOR_ATTR_TEMP_MAX_HYST(3),
+	SENSOR_ATTR_TEMP_MAX_HYST(4),
+	SENSOR_ATTR_TEMP_MAX_HYST(5),
+	SENSOR_ATTR_TEMP_MAX_HYST(6),
+	SENSOR_ATTR_TEMP_MAX_HYST(7),
+};
+
+#define SENSOR_ATTR_TEMP_ALARM(ix) \
+	SENSOR_ATTR_2(temp##ix##_alarm, S_IRUGO, \
+		show_temp, NULL, SHOW_TEMP_ALARM, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_alarm[] = {
+	SENSOR_ATTR_TEMP_ALARM(1),
+	SENSOR_ATTR_TEMP_ALARM(2),
+	SENSOR_ATTR_TEMP_ALARM(3),
+	SENSOR_ATTR_TEMP_ALARM(4),
+	SENSOR_ATTR_TEMP_ALARM(5),
+	SENSOR_ATTR_TEMP_ALARM(6),
+	SENSOR_ATTR_TEMP_ALARM(7),
+};
+
+#define SENSOR_ATTR_FAN(ix) \
+	SENSOR_ATTR_2(fan##ix##_input, S_IRUGO, \
+		show_fan, NULL, SHOW_FAN_INPUT, ix-1), \
+	SENSOR_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \
+		show_fan, set_fan, SHOW_SET_FAN_MIN, ix-1), \
+	SENSOR_ATTR_2(fan##ix##_div, S_IRUGO | S_IWUSR, \
+		show_fan, set_fan, SHOW_SET_FAN_DIV, ix-1), \
+	SENSOR_ATTR_2(fan##ix##_alarm, S_IRUGO, \
+		show_fan, NULL, SHOW_FAN_ALARM, ix-1)
+
+#define SENSOR_ATTR_PWM(ix) \
+	SENSOR_ATTR_2(pwm##ix, S_IRUGO, \
+		show_pwm, NULL, SHOW_PWM, ix-1), \
+	SENSOR_ATTR_2(pwm##ix##_enable, S_IRUGO | S_IWUSR, \
+		show_pwm, set_pwm, SHOW_SET_PWM_ENABLE, ix-1), \
+	SENSOR_ATTR_2(pwm##ix##_auto_channels_temp, S_IRUGO | S_IWUSR, \
+		show_pwm, set_pwm, SHOW_SET_PWM_AUTO_CHANNELS_TEMP, ix-1)
+
+#define SENSOR_ATTR_PWM_FREQ(ix) \
+	SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO | S_IWUSR, \
+		show_pwm, set_pwm, SHOW_SET_PWM_FREQ, ix-1)
+
+#define SENSOR_ATTR_PWM_FREQ_RO(ix) \
+	SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO, \
+		show_pwm, NULL, SHOW_SET_PWM_FREQ, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP(ix, ap) \
+	SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO | S_IWUSR, \
+		show_pwm_auto_point_temp, set_pwm_auto_point_temp, \
+		ap-1, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(ix, ap) \
+	SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO, \
+		show_pwm_auto_point_temp, NULL, \
+		ap-1, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_PWM(ix, ap) \
+	SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO | S_IWUSR, \
+		show_pwm_auto_point_pwm, set_pwm_auto_point_pwm, \
+		ap-1, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(ix, ap) \
+	SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO, \
+		show_pwm_auto_point_pwm, NULL, \
+		ap-1, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_fan_pwm[] = {
+	SENSOR_ATTR_FAN(1),
+	SENSOR_ATTR_FAN(2),
+	SENSOR_ATTR_PWM(1),
+	SENSOR_ATTR_PWM(2),
+	SENSOR_ATTR_PWM_FREQ(1),
+	SENSOR_ATTR_PWM_FREQ_RO(2),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 1),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 2),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 3),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 4),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 1),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 2),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 3),
+	SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 4),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 1),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 2),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 3),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 4),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 1),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 2),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 3),
+	SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 4),
+};
+
+static struct device_attribute vt1211_sysfs_misc[] = {
+	__ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm),
+	__ATTR(cpu0_vid, S_IRUGO, show_vid, NULL),
+	__ATTR(name, S_IRUGO, show_name, NULL),
+	__ATTR(alarms, S_IRUGO, show_alarms, NULL),
+};
+
+/* ---------------------------------------------------------------------
+ * Device registration and initialization
+ * --------------------------------------------------------------------- */
+
+static void __devinit vt1211_init_device(struct vt1211_data *data)
+{
+	/* set VRM */
+	data->vrm = vid_which_vrm();
+
+	/* Read (and initialize) UCH config */
+	data->uch_config = vt1211_read8(data, VT1211_REG_UCH_CONFIG);
+	if (uch_config > -1) {
+		data->uch_config = (data->uch_config & 0x83) |
+				   (uch_config << 2);
+		vt1211_write8(data, VT1211_REG_UCH_CONFIG, data->uch_config);
+	}
+
+	/* Initialize the interrupt mode (if request at module load time).
+	 * The VT1211 implements 3 different modes for clearing interrupts:
+	 * 0: Clear INT when status register is read. Regenerate INT as long
+	 *    as temp stays above hysteresis limit.
+	 * 1: Clear INT when status register is read. DON'T regenerate INT
+	 *    until temp falls below hysteresis limit and exceeds hot limit
+	 *    again.
+	 * 2: Clear INT when temp falls below max limit.
+	 *
+	 * The driver only allows to force mode 0 since that's the only one
+	 * that makes sense for 'sensors' */
+	if (int_mode == 0) {
+		vt1211_write8(data, VT1211_REG_TEMP1_CONFIG, 0);
+		vt1211_write8(data, VT1211_REG_TEMP2_CONFIG, 0);
+	}
+
+	/* Fill in some hard wired values into our data struct */
+	data->pwm_auto_pwm[0][3] = 255;
+	data->pwm_auto_pwm[1][3] = 255;
+}
+
+static void vt1211_remove_sysfs(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_in_input); i++) {
+		device_remove_file(dev,
+			&vt1211_sysfs_in_input[i].dev_attr);
+		device_remove_file(dev,
+			&vt1211_sysfs_in_min[i].dev_attr);
+		device_remove_file(dev,
+			&vt1211_sysfs_in_max[i].dev_attr);
+		device_remove_file(dev,
+			&vt1211_sysfs_in_alarm[i].dev_attr);
+	}
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_temp_input); i++) {
+		device_remove_file(dev,
+			&vt1211_sysfs_temp_input[i].dev_attr);
+		device_remove_file(dev,
+			&vt1211_sysfs_temp_max[i].dev_attr);
+		device_remove_file(dev,
+			&vt1211_sysfs_temp_max_hyst[i].dev_attr);
+		device_remove_file(dev,
+			&vt1211_sysfs_temp_alarm[i].dev_attr);
+	}
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) {
+		device_remove_file(dev,
+			&vt1211_sysfs_fan_pwm[i].dev_attr);
+	}
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) {
+		device_remove_file(dev, &vt1211_sysfs_misc[i]);
+	}
+}
+
+static int __devinit vt1211_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct vt1211_data *data;
+	struct resource *res;
+	int i, err;
+
+	if (!(data = kzalloc(sizeof(struct vt1211_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		dev_err(dev, "Out of memory\n");
+		goto EXIT;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	data->addr = res->start;
+	data->name = DRVNAME;
+	mutex_init(&data->update_lock);
+
+	platform_set_drvdata(pdev, data);
+
+	/* Initialize the VT1211 chip */
+	vt1211_init_device(data);
+
+	/* Create sysfs interface files */
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_in_input); i++) {
+		if (ISVOLT(i, data->uch_config)) {
+			if ((err = device_create_file(dev,
+				&vt1211_sysfs_in_input[i].dev_attr)) ||
+			    (err = device_create_file(dev,
+				&vt1211_sysfs_in_min[i].dev_attr)) ||
+			    (err = device_create_file(dev,
+				&vt1211_sysfs_in_max[i].dev_attr)) ||
+			    (err = device_create_file(dev,
+				&vt1211_sysfs_in_alarm[i].dev_attr))) {
+				goto EXIT_DEV_REMOVE;
+			}
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_temp_input); i++) {
+		if (ISTEMP(i, data->uch_config)) {
+			if ((err = device_create_file(dev,
+				&vt1211_sysfs_temp_input[i].dev_attr)) ||
+			    (err = device_create_file(dev,
+				&vt1211_sysfs_temp_max[i].dev_attr)) ||
+			    (err = device_create_file(dev,
+				&vt1211_sysfs_temp_max_hyst[i].dev_attr)) ||
+			    (err = device_create_file(dev,
+				&vt1211_sysfs_temp_alarm[i].dev_attr))) {
+				goto EXIT_DEV_REMOVE;
+			}
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) {
+		err = device_create_file(dev,
+			&vt1211_sysfs_fan_pwm[i].dev_attr);
+		if (err) {
+			goto EXIT_DEV_REMOVE;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) {
+		err = device_create_file(dev,
+		       &vt1211_sysfs_misc[i]);
+		if (err) {
+			goto EXIT_DEV_REMOVE;
+		}
+	}
+
+	/* Register device */
+	data->class_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		dev_err(dev, "Class registration failed (%d)\n", err);
+		goto EXIT_DEV_REMOVE_SILENT;
+	}
+
+	return 0;
+
+EXIT_DEV_REMOVE:
+	dev_err(dev, "Sysfs interface creation failed (%d)\n", err);
+EXIT_DEV_REMOVE_SILENT:
+	vt1211_remove_sysfs(pdev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+EXIT:
+	return err;
+}
+
+static int __devexit vt1211_remove(struct platform_device *pdev)
+{
+	struct vt1211_data *data = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(data->class_dev);
+	vt1211_remove_sysfs(pdev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+
+	return 0;
+}
+
+static struct platform_driver vt1211_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name  = DRVNAME,
+	},
+	.probe  = vt1211_probe,
+	.remove = __devexit_p(vt1211_remove),
+};
+
+static int __init vt1211_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + 0x7f,
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Device allocation failed (%d)\n",
+		       err);
+		goto EXIT;
+	}
+
+	res.name = pdev->name;
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device resource addition failed "
+		       "(%d)\n", err);
+		goto EXIT_DEV_PUT;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+		       err);
+		goto EXIT_DEV_PUT;
+	}
+
+	return 0;
+
+EXIT_DEV_PUT:
+	platform_device_put(pdev);
+EXIT:
+	return err;
+}
+
+static int __init vt1211_find(unsigned short *address)
+{
+	int err = -ENODEV;
+
+	superio_enter();
+
+	if (superio_inb(SIO_VT1211_DEVID) != SIO_VT1211_ID) {
+		goto EXIT;
+	}
+
+	superio_select(SIO_VT1211_LDN_HWMON);
+
+	if ((superio_inb(SIO_VT1211_ACTIVE) & 1) == 0) {
+		printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
+		       "skipping\n");
+		goto EXIT;
+	}
+
+	*address = ((superio_inb(SIO_VT1211_BADDR) << 8) |
+		    (superio_inb(SIO_VT1211_BADDR + 1))) & 0xff00;
+	if (*address == 0) {
+		printk(KERN_WARNING DRVNAME ": Base address is not set, "
+		       "skipping\n");
+		goto EXIT;
+	}
+
+	err = 0;
+	printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
+	       "revision %u\n", *address, superio_inb(SIO_VT1211_DEVREV));
+
+EXIT:
+	superio_exit();
+	return err;
+}
+
+static int __init vt1211_init(void)
+{
+	int err;
+	unsigned short address = 0;
+
+	err = vt1211_find(&address);
+	if (err) {
+		goto EXIT;
+	}
+
+	if ((uch_config < -1) || (uch_config > 31)) {
+		err = -EINVAL;
+		printk(KERN_WARNING DRVNAME ": Invalid UCH configuration %d. "
+		       "Choose a value between 0 and 31.\n", uch_config);
+	  goto EXIT;
+	}
+
+	if ((int_mode < -1) || (int_mode > 0)) {
+		err = -EINVAL;
+		printk(KERN_WARNING DRVNAME ": Invalid interrupt mode %d. "
+		       "Only mode 0 is supported.\n", int_mode);
+	  goto EXIT;
+	}
+
+	err = platform_driver_register(&vt1211_driver);
+	if (err) {
+		goto EXIT;
+	}
+
+	/* Sets global pdev as a side effect */
+	err = vt1211_device_add(address);
+	if (err) {
+		goto EXIT_DRV_UNREGISTER;
+	}
+
+	return 0;
+
+EXIT_DRV_UNREGISTER:
+	platform_driver_unregister(&vt1211_driver);
+EXIT:
+	return err;
+}
+
+static void __exit vt1211_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&vt1211_driver);
+}
+
+MODULE_AUTHOR("Juerg Haefliger <juergh@gmail.com>");
+MODULE_DESCRIPTION("VT1211 sensors");
+MODULE_LICENSE("GPL");
+
+module_init(vt1211_init);
+module_exit(vt1211_exit);
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 236ccf0..93f93d4 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -451,37 +451,6 @@
 define_temperature_sysfs(5);
 define_temperature_sysfs(6);
 
-#define CFG_INFO_TEMP(id)	{ &sensor_dev_attr_temp##id##_input.dev_attr, \
-				&sensor_dev_attr_temp##id##_max_hyst.dev_attr, \
-				&sensor_dev_attr_temp##id##_max.dev_attr }
-#define CFG_INFO_VOLT(id)	{ &sensor_dev_attr_in##id##_input.dev_attr, \
-				&sensor_dev_attr_in##id##_min.dev_attr, \
-				&sensor_dev_attr_in##id##_max.dev_attr }
-
-struct str_device_attr_table {
-	struct device_attribute *input;
-	struct device_attribute *min;
-	struct device_attribute *max;
-};
-
-static struct str_device_attr_table cfg_info_temp[] = {
-	{ &dev_attr_temp1_input, &dev_attr_temp1_max_hyst, &dev_attr_temp1_max },
-	CFG_INFO_TEMP(2),
-	CFG_INFO_TEMP(3),
-	CFG_INFO_TEMP(4),
-	CFG_INFO_TEMP(5),
-	CFG_INFO_TEMP(6)
-};
-
-static struct str_device_attr_table cfg_info_volt[] = {
-	CFG_INFO_VOLT(0),
-	CFG_INFO_VOLT(1),
-	CFG_INFO_VOLT(2),
-	CFG_INFO_VOLT(3),
-	CFG_INFO_VOLT(4),
-	{ &dev_attr_in5_input, &dev_attr_in5_min, &dev_attr_in5_max }
-};
-
 /* Fans */
 static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -585,6 +554,107 @@
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *vt8231_attributes_temps[6][4] = {
+	{
+		&dev_attr_temp1_input.attr,
+		&dev_attr_temp1_max_hyst.attr,
+		&dev_attr_temp1_max.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp2_input.dev_attr.attr,
+		&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+		&sensor_dev_attr_temp2_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp3_input.dev_attr.attr,
+		&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+		&sensor_dev_attr_temp3_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp4_input.dev_attr.attr,
+		&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
+		&sensor_dev_attr_temp4_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp5_input.dev_attr.attr,
+		&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
+		&sensor_dev_attr_temp5_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_temp6_input.dev_attr.attr,
+		&sensor_dev_attr_temp6_max_hyst.dev_attr.attr,
+		&sensor_dev_attr_temp6_max.dev_attr.attr,
+		NULL
+	}
+};
+
+static const struct attribute_group vt8231_group_temps[6] = {
+	{ .attrs = vt8231_attributes_temps[0] },
+	{ .attrs = vt8231_attributes_temps[1] },
+	{ .attrs = vt8231_attributes_temps[2] },
+	{ .attrs = vt8231_attributes_temps[3] },
+	{ .attrs = vt8231_attributes_temps[4] },
+	{ .attrs = vt8231_attributes_temps[5] },
+};
+
+static struct attribute *vt8231_attributes_volts[6][4] = {
+	{
+		&sensor_dev_attr_in0_input.dev_attr.attr,
+		&sensor_dev_attr_in0_min.dev_attr.attr,
+		&sensor_dev_attr_in0_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_in1_input.dev_attr.attr,
+		&sensor_dev_attr_in1_min.dev_attr.attr,
+		&sensor_dev_attr_in1_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_in2_input.dev_attr.attr,
+		&sensor_dev_attr_in2_min.dev_attr.attr,
+		&sensor_dev_attr_in2_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_in3_input.dev_attr.attr,
+		&sensor_dev_attr_in3_min.dev_attr.attr,
+		&sensor_dev_attr_in3_max.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_in4_input.dev_attr.attr,
+		&sensor_dev_attr_in4_min.dev_attr.attr,
+		&sensor_dev_attr_in4_max.dev_attr.attr,
+		NULL
+	}, {
+		&dev_attr_in5_input.attr,
+		&dev_attr_in5_min.attr,
+		&dev_attr_in5_max.attr,
+		NULL
+	}
+};
+
+static const struct attribute_group vt8231_group_volts[6] = {
+	{ .attrs = vt8231_attributes_volts[0] },
+	{ .attrs = vt8231_attributes_volts[1] },
+	{ .attrs = vt8231_attributes_volts[2] },
+	{ .attrs = vt8231_attributes_volts[3] },
+	{ .attrs = vt8231_attributes_volts[4] },
+	{ .attrs = vt8231_attributes_volts[5] },
+};
+
+static struct attribute *vt8231_attributes[] = {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static const struct attribute_group vt8231_group = {
+	.attrs = vt8231_attributes,
+};
+
 static struct i2c_driver vt8231_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
@@ -671,43 +741,43 @@
 	vt8231_init_client(client);
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
+	if ((err = sysfs_create_group(&client->dev.kobj, &vt8231_group)))
 		goto exit_detach;
-	}
 
 	/* Must update device information to find out the config field */
 	data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG);
 
-	for (i = 0; i < ARRAY_SIZE(cfg_info_temp); i++) {
+	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) {
 		if (ISTEMP(i, data->uch_config)) {
-			device_create_file(&client->dev,
-					   cfg_info_temp[i].input);
-			device_create_file(&client->dev, cfg_info_temp[i].max);
-			device_create_file(&client->dev, cfg_info_temp[i].min);
+			if ((err = sysfs_create_group(&client->dev.kobj,
+					&vt8231_group_temps[i])))
+				goto exit_remove_files;
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(cfg_info_volt); i++) {
+	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) {
 		if (ISVOLT(i, data->uch_config)) {
-			device_create_file(&client->dev,
-					   cfg_info_volt[i].input);
-			device_create_file(&client->dev, cfg_info_volt[i].max);
-			device_create_file(&client->dev, cfg_info_volt[i].min);
+			if ((err = sysfs_create_group(&client->dev.kobj,
+					&vt8231_group_volts[i])))
+				goto exit_remove_files;
 		}
 	}
 
-	device_create_file(&client->dev, &sensor_dev_attr_fan1_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_fan2_input.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_fan1_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_fan2_min.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_fan1_div.dev_attr);
-	device_create_file(&client->dev, &sensor_dev_attr_fan2_div.dev_attr);
-
-	device_create_file(&client->dev, &dev_attr_alarms);
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove_files;
+	}
 	return 0;
 
+exit_remove_files:
+	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
+		sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]);
+
+	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
+		sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]);
+
+	sysfs_remove_group(&client->dev.kobj, &vt8231_group);
 exit_detach:
 	i2c_detach_client(client);
 exit_free:
@@ -720,10 +790,18 @@
 static int vt8231_detach_client(struct i2c_client *client)
 {
 	struct vt8231_data *data = i2c_get_clientdata(client);
-	int err;
+	int err, i;
 
 	hwmon_device_unregister(data->class_dev);
 
+	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
+		sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]);
+
+	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
+		sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]);
+
+	sysfs_remove_group(&client->dev.kobj, &vt8231_group);
+
 	if ((err = i2c_detach_client(client))) {
 		return err;
 	}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index b21d6b9..833faa2 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -2,6 +2,9 @@
     w83627ehf - Driver for the hardware monitoring functionality of
                 the Winbond W83627EHF Super-I/O chip
     Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2006  Yuan Mu (Winbond),
+                        Rudolf Marek <r.marek@sh.cvut.cz>
+                        David Hubbard <david.c.hubbard@gmail.com>
 
     Shamelessly ripped from the w83627hf driver
     Copyright (C) 2003  Mark Studebaker
@@ -29,8 +32,8 @@
 
     Supports the following chips:
 
-    Chip        #vin    #fan    #pwm    #temp   chip_id man_id
-    w83627ehf   10      5       -       3       0x88    0x5ca3
+    Chip        #vin    #fan    #pwm    #temp   chip_id    man_id
+    w83627ehf   10      5       4       3       0x88,0xa1  0x5ca3
 */
 
 #include <linux/module.h>
@@ -145,10 +148,44 @@
 #define W83627EHF_REG_ALARM2		0x45A
 #define W83627EHF_REG_ALARM3		0x45B
 
+/* SmartFan registers */
+/* DC or PWM output fan configuration */
+static const u8 W83627EHF_REG_PWM_ENABLE[] = {
+	0x04,			/* SYS FAN0 output mode and PWM mode */
+	0x04,			/* CPU FAN0 output mode and PWM mode */
+	0x12,			/* AUX FAN mode */
+	0x62,			/* CPU fan1 mode */
+};
+
+static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 };
+static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 };
+
+/* FAN Duty Cycle, be used to control */
+static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
+static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
+static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
+
+
+/* Advanced Fan control, some values are common for all fans */
+static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
+static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 };
+
 /*
  * Conversions
  */
 
+/* 1 is PWM mode, output in ms */
+static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
+{
+	return mode ? 100 * reg : 400 * reg;
+}
+
+static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
+{
+	return SENSORS_LIMIT((mode ? (msec + 50) / 100 :
+						(msec + 200) / 400), 1, 255);
+}
+
 static inline unsigned int
 fan_from_reg(u8 reg, unsigned int div)
 {
@@ -170,12 +207,12 @@
 }
 
 static inline s8
-temp1_to_reg(int temp)
+temp1_to_reg(int temp, int min, int max)
 {
-	if (temp <= -128000)
-		return -128;
-	if (temp >= 127000)
-		return 127;
+	if (temp <= min)
+		return min / 1000;
+	if (temp >= max)
+		return max / 1000;
 	if (temp < 0)
 		return (temp - 500) / 1000;
 	return (temp + 500) / 1000;
@@ -223,6 +260,16 @@
 	s16 temp_max[2];
 	s16 temp_max_hyst[2];
 	u32 alarms;
+
+	u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
+	u8 pwm_enable[4]; /* 1->manual
+			     2->thermal cruise (also called SmartFan I) */
+	u8 pwm[4];
+	u8 target_temp[4];
+	u8 tolerance[4];
+
+	u8 fan_min_output[4]; /* minimum fan speed */
+	u8 fan_stop_time[4];
 };
 
 static inline int is_word_sized(u16 reg)
@@ -349,6 +396,7 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -416,6 +464,34 @@
 			}
 		}
 
+		for (i = 0; i < 4; i++) {
+			/* pwmcfg, tolarance mapped for i=0, i=1 to same reg */
+			if (i != 1) {
+				pwmcfg = w83627ehf_read_value(client,
+						W83627EHF_REG_PWM_ENABLE[i]);
+				tolerance = w83627ehf_read_value(client,
+						W83627EHF_REG_TOLERANCE[i]);
+			}
+			data->pwm_mode[i] =
+				((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
+				? 0 : 1;
+			data->pwm_enable[i] =
+					((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
+						& 3) + 1;
+			data->pwm[i] = w83627ehf_read_value(client,
+						W83627EHF_REG_PWM[i]);
+			data->fan_min_output[i] = w83627ehf_read_value(client,
+						W83627EHF_REG_FAN_MIN_OUTPUT[i]);
+			data->fan_stop_time[i] = w83627ehf_read_value(client,
+						W83627EHF_REG_FAN_STOP_TIME[i]);
+			data->target_temp[i] =
+				w83627ehf_read_value(client,
+					W83627EHF_REG_TARGET[i]) &
+					(data->pwm_mode[i] == 1 ? 0x7f : 0xff);
+			data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))
+									& 0x0f;
+		}
+
 		/* Measured temperatures and limits */
 		data->temp1 = w83627ehf_read_value(client,
 			      W83627EHF_REG_TEMP1);
@@ -546,14 +622,6 @@
        SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
 };
 
-static void device_create_file_in(struct device *dev, int i)
-{
-	device_create_file(dev, &sda_in_input[i].dev_attr);
-	device_create_file(dev, &sda_in_alarm[i].dev_attr);
-	device_create_file(dev, &sda_in_min[i].dev_attr);
-	device_create_file(dev, &sda_in_max[i].dev_attr);
-}
-
 #define show_fan_reg(reg) \
 static ssize_t \
 show_##reg(struct device *dev, struct device_attribute *attr, \
@@ -681,14 +749,6 @@
 	SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
 };
 
-static void device_create_file_fan(struct device *dev, int i)
-{
-	device_create_file(dev, &sda_fan_input[i].dev_attr);
-	device_create_file(dev, &sda_fan_alarm[i].dev_attr);
-	device_create_file(dev, &sda_fan_div[i].dev_attr);
-	device_create_file(dev, &sda_fan_min[i].dev_attr);
-}
-
 #define show_temp1_reg(reg) \
 static ssize_t \
 show_##reg(struct device *dev, struct device_attribute *attr, \
@@ -711,7 +771,7 @@
 	u32 val = simple_strtoul(buf, NULL, 10); \
  \
 	mutex_lock(&data->update_lock); \
-	data->temp1_##reg = temp1_to_reg(val); \
+	data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \
 	w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
 			      data->temp1_##reg); \
 	mutex_unlock(&data->update_lock); \
@@ -777,10 +837,309 @@
 	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
 };
 
+#define show_pwm_reg(reg) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
+				char *buf) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf, "%d\n", data->reg[nr]); \
+}
+
+show_pwm_reg(pwm_mode)
+show_pwm_reg(pwm_enable)
+show_pwm_reg(pwm)
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u16 reg;
+
+	if (val > 1)
+		return -EINVAL;
+	mutex_lock(&data->update_lock);
+	reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
+	data->pwm_mode[nr] = val;
+	reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]);
+	if (!val)
+		reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr];
+	w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->pwm[nr] = val;
+	w83627ehf_write_value(client, W83627EHF_REG_PWM[nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+store_pwm_enable(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u16 reg;
+
+	if (!val || (val > 2))	/* only modes 1 and 2 are supported */
+		return -EINVAL;
+	mutex_lock(&data->update_lock);
+	reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
+	data->pwm_enable[nr] = val;
+	reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
+	reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
+	w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+
+#define show_tol_temp(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+				char *buf) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf, "%d\n", temp1_from_reg(data->reg[nr])); \
+}
+
+show_tol_temp(tolerance)
+show_tol_temp(target_temp)
+
+static ssize_t
+store_target_temp(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000);
+
+	mutex_lock(&data->update_lock);
+	data->target_temp[nr] = val;
+	w83627ehf_write_value(client, W83627EHF_REG_TARGET[nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+store_tolerance(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	u16 reg;
+	/* Limit the temp to 0C - 15C */
+	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000);
+
+	mutex_lock(&data->update_lock);
+	reg = w83627ehf_read_value(client, W83627EHF_REG_TOLERANCE[nr]);
+	data->tolerance[nr] = val;
+	if (nr == 1)
+		reg = (reg & 0x0f) | (val << 4);
+	else
+		reg = (reg & 0xf0) | val;
+	w83627ehf_write_value(client, W83627EHF_REG_TOLERANCE[nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static struct sensor_device_attribute sda_pwm[] = {
+	SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
+	SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
+	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
+	SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
+};
+
+static struct sensor_device_attribute sda_pwm_mode[] = {
+	SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+		    store_pwm_mode, 0),
+	SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+		    store_pwm_mode, 1),
+	SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+		    store_pwm_mode, 2),
+	SENSOR_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+		    store_pwm_mode, 3),
+};
+
+static struct sensor_device_attribute sda_pwm_enable[] = {
+	SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+		    store_pwm_enable, 0),
+	SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+		    store_pwm_enable, 1),
+	SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+		    store_pwm_enable, 2),
+	SENSOR_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+		    store_pwm_enable, 3),
+};
+
+static struct sensor_device_attribute sda_target_temp[] = {
+	SENSOR_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp,
+		    store_target_temp, 0),
+	SENSOR_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp,
+		    store_target_temp, 1),
+	SENSOR_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp,
+		    store_target_temp, 2),
+	SENSOR_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp,
+		    store_target_temp, 3),
+};
+
+static struct sensor_device_attribute sda_tolerance[] = {
+	SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+		    store_tolerance, 0),
+	SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+		    store_tolerance, 1),
+	SENSOR_ATTR(pwm3_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+		    store_tolerance, 2),
+	SENSOR_ATTR(pwm4_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+		    store_tolerance, 3),
+};
+
+/* Smart Fan registers */
+
+#define fan_functions(reg, REG) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+		       char *buf) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf, "%d\n", data->reg[nr]); \
+}\
+static ssize_t \
+store_##reg(struct device *dev, struct device_attribute *attr, \
+			    const char *buf, size_t count) \
+{\
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
+	mutex_lock(&data->update_lock); \
+	data->reg[nr] = val; \
+	w83627ehf_write_value(client, W83627EHF_REG_##REG[nr],  val); \
+	mutex_unlock(&data->update_lock); \
+	return count; \
+}
+
+fan_functions(fan_min_output, FAN_MIN_OUTPUT)
+
+#define fan_time_functions(reg, REG) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+				char *buf) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf, "%d\n", \
+			step_time_from_reg(data->reg[nr], data->pwm_mode[nr])); \
+} \
+\
+static ssize_t \
+store_##reg(struct device *dev, struct device_attribute *attr, \
+			const char *buf, size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \
+					data->pwm_mode[nr]); \
+	mutex_lock(&data->update_lock); \
+	data->reg[nr] = val; \
+	w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \
+	mutex_unlock(&data->update_lock); \
+	return count; \
+} \
+
+fan_time_functions(fan_stop_time, FAN_STOP_TIME)
+
+
+static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
+	SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+		    store_fan_stop_time, 3),
+	SENSOR_ATTR(pwm4_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+		    store_fan_min_output, 3),
+};
+
+static struct sensor_device_attribute sda_sf3_arrays[] = {
+	SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+		    store_fan_stop_time, 0),
+	SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+		    store_fan_stop_time, 1),
+	SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+		    store_fan_stop_time, 2),
+	SENSOR_ATTR(pwm1_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+		    store_fan_min_output, 0),
+	SENSOR_ATTR(pwm2_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+		    store_fan_min_output, 1),
+	SENSOR_ATTR(pwm3_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+		    store_fan_min_output, 2),
+};
+
 /*
  * Driver and client management
  */
 
+static void w83627ehf_device_remove_files(struct device *dev)
+{
+	/* some entries in the following arrays may not have been used in
+	 * device_create_file(), but device_remove_file() will ignore them */
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
+		device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
+		device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
+	for (i = 0; i < 10; i++) {
+		device_remove_file(dev, &sda_in_input[i].dev_attr);
+		device_remove_file(dev, &sda_in_alarm[i].dev_attr);
+		device_remove_file(dev, &sda_in_min[i].dev_attr);
+		device_remove_file(dev, &sda_in_max[i].dev_attr);
+	}
+	for (i = 0; i < 5; i++) {
+		device_remove_file(dev, &sda_fan_input[i].dev_attr);
+		device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
+		device_remove_file(dev, &sda_fan_div[i].dev_attr);
+		device_remove_file(dev, &sda_fan_min[i].dev_attr);
+	}
+	for (i = 0; i < 4; i++) {
+		device_remove_file(dev, &sda_pwm[i].dev_attr);
+		device_remove_file(dev, &sda_pwm_mode[i].dev_attr);
+		device_remove_file(dev, &sda_pwm_enable[i].dev_attr);
+		device_remove_file(dev, &sda_target_temp[i].dev_attr);
+		device_remove_file(dev, &sda_tolerance[i].dev_attr);
+	}
+	for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
+		device_remove_file(dev, &sda_temp[i].dev_attr);
+}
+
 static struct i2c_driver w83627ehf_driver;
 
 static void w83627ehf_init_client(struct i2c_client *client)
@@ -810,6 +1169,7 @@
 	struct i2c_client *client;
 	struct w83627ehf_data *data;
 	struct device *dev;
+	u8 fan4pin, fan5pin;
 	int i, err = 0;
 
 	if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
@@ -848,35 +1208,87 @@
 		data->fan_min[i] = w83627ehf_read_value(client,
 				   W83627EHF_REG_FAN_MIN[i]);
 
+	/* fan4 and fan5 share some pins with the GPIO and serial flash */
+
+	superio_enter();
+	fan5pin = superio_inb(0x24) & 0x2;
+	fan4pin = superio_inb(0x29) & 0x6;
+	superio_exit();
+
 	/* It looks like fan4 and fan5 pins can be alternatively used
 	   as fan on/off switches */
+
 	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
 	i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
-	if (i & (1 << 2))
+	if ((i & (1 << 2)) && (!fan4pin))
 		data->has_fan |= (1 << 3);
-	if (i & (1 << 0))
+	if ((i & (1 << 0)) && (!fan5pin))
 		data->has_fan |= (1 << 4);
 
 	/* Register sysfs hooks */
+  	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
+		if ((err = device_create_file(dev,
+			&sda_sf3_arrays[i].dev_attr)))
+			goto exit_remove;
+
+	/* if fan4 is enabled create the sf3 files for it */
+	if (data->has_fan & (1 << 3))
+		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
+			if ((err = device_create_file(dev,
+				&sda_sf3_arrays_fan4[i].dev_attr)))
+				goto exit_remove;
+		}
+
+	for (i = 0; i < 10; i++)
+		if ((err = device_create_file(dev, &sda_in_input[i].dev_attr))
+			|| (err = device_create_file(dev,
+				&sda_in_alarm[i].dev_attr))
+			|| (err = device_create_file(dev,
+				&sda_in_min[i].dev_attr))
+			|| (err = device_create_file(dev,
+				&sda_in_max[i].dev_attr)))
+			goto exit_remove;
+
+	for (i = 0; i < 5; i++) {
+		if (data->has_fan & (1 << i)) {
+			if ((err = device_create_file(dev,
+					&sda_fan_input[i].dev_attr))
+				|| (err = device_create_file(dev,
+					&sda_fan_alarm[i].dev_attr))
+				|| (err = device_create_file(dev,
+					&sda_fan_div[i].dev_attr))
+				|| (err = device_create_file(dev,
+					&sda_fan_min[i].dev_attr)))
+				goto exit_remove;
+			if (i < 4 && /* w83627ehf only has 4 pwm */
+				((err = device_create_file(dev,
+					&sda_pwm[i].dev_attr))
+				|| (err = device_create_file(dev,
+					&sda_pwm_mode[i].dev_attr))
+				|| (err = device_create_file(dev,
+					&sda_pwm_enable[i].dev_attr))
+				|| (err = device_create_file(dev,
+					&sda_target_temp[i].dev_attr))
+				|| (err = device_create_file(dev,
+					&sda_tolerance[i].dev_attr))))
+				goto exit_remove;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
+		if ((err = device_create_file(dev, &sda_temp[i].dev_attr)))
+			goto exit_remove;
+
 	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove;
 	}
 
-	for (i = 0; i < 10; i++)
-		device_create_file_in(dev, i);
-
-	for (i = 0; i < 5; i++) {
-		if (data->has_fan & (1 << i))
-			device_create_file_fan(dev, i);
-	}
-	for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
-		device_create_file(dev, &sda_temp[i].dev_attr);
-
 	return 0;
 
-exit_detach:
+exit_remove:
+	w83627ehf_device_remove_files(dev);
 	i2c_detach_client(client);
 exit_free:
 	kfree(data);
@@ -892,6 +1304,7 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
+	w83627ehf_device_remove_files(&client->dev);
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 30295028..dfdc29c7 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -512,13 +512,6 @@
 static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
 	show_regs_in_max0, store_regs_in_max0);
 
-#define device_create_file_in(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-device_create_file(&client->dev, &dev_attr_in##offset##_min); \
-device_create_file(&client->dev, &dev_attr_in##offset##_max); \
-} while (0)
-
 #define show_fan_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -576,12 +569,6 @@
 sysfs_fan_offset(3);
 sysfs_fan_min_offset(3);
 
-#define device_create_file_fan(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
-} while (0)
-
 #define show_temp_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -656,13 +643,6 @@
 sysfs_temp_offsets(2);
 sysfs_temp_offsets(3);
 
-#define device_create_file_temp(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
-} while (0)
-
 static ssize_t
 show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -670,8 +650,6 @@
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 static ssize_t
 show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -692,8 +670,6 @@
 	return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm)
 
 static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -702,8 +678,6 @@
 	return sprintf(buf, "%ld\n", (long) data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-#define device_create_file_alarms(client) \
-device_create_file(&client->dev, &dev_attr_alarms)
 
 #define show_beep_reg(REG, reg) \
 static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
@@ -766,12 +740,6 @@
 sysfs_beep(ENABLE, enable);
 sysfs_beep(MASK, mask);
 
-#define device_create_file_beep(client) \
-do { \
-device_create_file(&client->dev, &dev_attr_beep_enable); \
-device_create_file(&client->dev, &dev_attr_beep_mask); \
-} while (0)
-
 static ssize_t
 show_fan_div_reg(struct device *dev, char *buf, int nr)
 {
@@ -837,11 +805,6 @@
 sysfs_fan_div(2);
 sysfs_fan_div(3);
 
-#define device_create_file_fan_div(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-} while (0)
-
 static ssize_t
 show_pwm_reg(struct device *dev, char *buf, int nr)
 {
@@ -896,11 +859,6 @@
 sysfs_pwm(2);
 sysfs_pwm(3);
 
-#define device_create_file_pwm(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_pwm##offset); \
-} while (0)
-
 static ssize_t
 show_sensor_reg(struct device *dev, char *buf, int nr)
 {
@@ -972,12 +930,6 @@
 sysfs_sensor(2);
 sysfs_sensor(3);
 
-#define device_create_file_sensor(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
-} while (0)
-
-
 static int __init w83627hf_find(int sioaddr, unsigned short *addr)
 {
 	u16 val;
@@ -1009,6 +961,85 @@
 	return 0;
 }
 
+static struct attribute *w83627hf_attributes[] = {
+	&dev_attr_in0_input.attr,
+	&dev_attr_in0_min.attr,
+	&dev_attr_in0_max.attr,
+	&dev_attr_in2_input.attr,
+	&dev_attr_in2_min.attr,
+	&dev_attr_in2_max.attr,
+	&dev_attr_in3_input.attr,
+	&dev_attr_in3_min.attr,
+	&dev_attr_in3_max.attr,
+	&dev_attr_in4_input.attr,
+	&dev_attr_in4_min.attr,
+	&dev_attr_in4_max.attr,
+	&dev_attr_in7_input.attr,
+	&dev_attr_in7_min.attr,
+	&dev_attr_in7_max.attr,
+	&dev_attr_in8_input.attr,
+	&dev_attr_in8_min.attr,
+	&dev_attr_in8_max.attr,
+
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_div.attr,
+	&dev_attr_fan2_input.attr,
+	&dev_attr_fan2_min.attr,
+	&dev_attr_fan2_div.attr,
+
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp1_max.attr,
+	&dev_attr_temp1_max_hyst.attr,
+	&dev_attr_temp1_type.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp2_max_hyst.attr,
+	&dev_attr_temp2_type.attr,
+
+	&dev_attr_alarms.attr,
+	&dev_attr_beep_enable.attr,
+	&dev_attr_beep_mask.attr,
+
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm2.attr,
+
+	NULL
+};
+
+static const struct attribute_group w83627hf_group = {
+	.attrs = w83627hf_attributes,
+};
+
+static struct attribute *w83627hf_attributes_opt[] = {
+	&dev_attr_in1_input.attr,
+	&dev_attr_in1_min.attr,
+	&dev_attr_in1_max.attr,
+	&dev_attr_in5_input.attr,
+	&dev_attr_in5_min.attr,
+	&dev_attr_in5_max.attr,
+	&dev_attr_in6_input.attr,
+	&dev_attr_in6_min.attr,
+	&dev_attr_in6_max.attr,
+
+	&dev_attr_fan3_input.attr,
+	&dev_attr_fan3_min.attr,
+	&dev_attr_fan3_div.attr,
+
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp3_max.attr,
+	&dev_attr_temp3_max_hyst.attr,
+	&dev_attr_temp3_type.attr,
+
+	&dev_attr_pwm3.attr,
+
+	NULL
+};
+
+static const struct attribute_group w83627hf_group_opt = {
+	.attrs = w83627hf_attributes_opt,
+};
+
 static int w83627hf_detect(struct i2c_adapter *adapter)
 {
 	int val, kind;
@@ -1108,62 +1139,72 @@
 	data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2));
 	data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
 
-	/* Register sysfs hooks */
+	/* Register common device attributes */
+	if ((err = sysfs_create_group(&new_client->dev.kobj, &w83627hf_group)))
+		goto ERROR3;
+
+	/* Register chip-specific device attributes */
+	if (kind == w83627hf || kind == w83697hf)
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_in5_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in5_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in5_max))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in6_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in6_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in6_max)))
+			goto ERROR4;
+
+	if (kind != w83697hf)
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_in1_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in1_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_in1_max))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_fan3_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_fan3_min))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_fan3_div))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_input))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_max))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_max_hyst))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_temp3_type)))
+			goto ERROR4;
+
+	if (kind != w83697hf && data->vid != 0xff)
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_cpu0_vid))
+		 || (err = device_create_file(&new_client->dev,
+					&dev_attr_vrm)))
+			goto ERROR4;
+
+	if (kind == w83627thf || kind == w83637hf || kind == w83687thf)
+		if ((err = device_create_file(&new_client->dev,
+					&dev_attr_pwm3)))
+			goto ERROR4;
+
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto ERROR3;
+		goto ERROR4;
 	}
 
-	device_create_file_in(new_client, 0);
-	if (kind != w83697hf)
-		device_create_file_in(new_client, 1);
-	device_create_file_in(new_client, 2);
-	device_create_file_in(new_client, 3);
-	device_create_file_in(new_client, 4);
-	if (kind == w83627hf || kind == w83697hf) {
-		device_create_file_in(new_client, 5);
-		device_create_file_in(new_client, 6);
-	}
-	device_create_file_in(new_client, 7);
-	device_create_file_in(new_client, 8);
-
-	device_create_file_fan(new_client, 1);
-	device_create_file_fan(new_client, 2);
-	if (kind != w83697hf)
-		device_create_file_fan(new_client, 3);
-
-	device_create_file_temp(new_client, 1);
-	device_create_file_temp(new_client, 2);
-	if (kind != w83697hf)
-		device_create_file_temp(new_client, 3);
-
-	if (kind != w83697hf && data->vid != 0xff) {
-		device_create_file_vid(new_client);
-		device_create_file_vrm(new_client);
-	}
-
-	device_create_file_fan_div(new_client, 1);
-	device_create_file_fan_div(new_client, 2);
-	if (kind != w83697hf)
-		device_create_file_fan_div(new_client, 3);
-
-	device_create_file_alarms(new_client);
-
-	device_create_file_beep(new_client);
-
-	device_create_file_pwm(new_client, 1);
-	device_create_file_pwm(new_client, 2);
-	if (kind == w83627thf || kind == w83637hf || kind == w83687thf)
-		device_create_file_pwm(new_client, 3);
-
-	device_create_file_sensor(new_client, 1);
-	device_create_file_sensor(new_client, 2);
-	if (kind != w83697hf)
-		device_create_file_sensor(new_client, 3);
-
 	return 0;
 
+      ERROR4:
+	sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group);
+	sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group_opt);
       ERROR3:
 	i2c_detach_client(new_client);
       ERROR2:
@@ -1181,6 +1222,9 @@
 
 	hwmon_device_unregister(data->class_dev);
 
+	sysfs_remove_group(&client->dev.kobj, &w83627hf_group);
+	sysfs_remove_group(&client->dev.kobj, &w83627hf_group_opt);
+
 	if ((err = i2c_detach_client(client)))
 		return err;
 
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 95221b1..a4584ec 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -41,6 +41,7 @@
 #include <linux/i2c-isa.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-vid.h>
+#include <linux/sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
@@ -360,13 +361,6 @@
 sysfs_in_offsets(7);
 sysfs_in_offsets(8);
 
-#define device_create_file_in(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-device_create_file(&client->dev, &dev_attr_in##offset##_min); \
-device_create_file(&client->dev, &dev_attr_in##offset##_max); \
-} while (0)
-
 #define show_fan_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -421,12 +415,6 @@
 sysfs_fan_offset(3);
 sysfs_fan_min_offset(3);
 
-#define device_create_file_fan(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
-} while (0)
-
 #define show_temp_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -497,13 +485,6 @@
 sysfs_temp_offsets(2);
 sysfs_temp_offsets(3);
 
-#define device_create_file_temp(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
-} while (0)
-
 static ssize_t
 show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -511,10 +492,8 @@
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 
-static
-DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
+
 static ssize_t
 show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -535,10 +514,8 @@
 	return count;
 }
 
-static
-DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm);
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
+
 static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -546,10 +523,8 @@
 	return sprintf(buf, "%u\n", data->alarms);
 }
 
-static
-DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-#define device_create_file_alarms(client) \
-device_create_file(&client->dev, &dev_attr_alarms);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+
 static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83781d_data *data = w83781d_update_device(dev);
@@ -615,12 +590,6 @@
 sysfs_beep(ENABLE, enable);
 sysfs_beep(MASK, mask);
 
-#define device_create_file_beep(client) \
-do { \
-device_create_file(&client->dev, &dev_attr_beep_enable); \
-device_create_file(&client->dev, &dev_attr_beep_mask); \
-} while (0)
-
 static ssize_t
 show_fan_div_reg(struct device *dev, char *buf, int nr)
 {
@@ -686,11 +655,6 @@
 sysfs_fan_div(2);
 sysfs_fan_div(3);
 
-#define device_create_file_fan_div(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-} while (0)
-
 static ssize_t
 show_pwm_reg(struct device *dev, char *buf, int nr)
 {
@@ -787,16 +751,6 @@
 sysfs_pwm(3);
 sysfs_pwm(4);
 
-#define device_create_file_pwm(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_pwm##offset); \
-} while (0)
-
-#define device_create_file_pwmenable(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_pwm##offset##_enable); \
-} while (0)
-
 static ssize_t
 show_sensor_reg(struct device *dev, char *buf, int nr)
 {
@@ -865,11 +819,6 @@
 sysfs_sensor(2);
 sysfs_sensor(3);
 
-#define device_create_file_sensor(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
-} while (0)
-
 /* This function is called when:
      * w83781d_driver is inserted (when this module is loaded), for each
        available adapter
@@ -994,11 +943,69 @@
 	return err;
 }
 
+#define IN_UNIT_ATTRS(X)			\
+	&dev_attr_in##X##_input.attr,		\
+	&dev_attr_in##X##_min.attr,		\
+	&dev_attr_in##X##_max.attr
+
+#define FAN_UNIT_ATTRS(X)			\
+	&dev_attr_fan##X##_input.attr,		\
+	&dev_attr_fan##X##_min.attr,		\
+	&dev_attr_fan##X##_div.attr
+
+#define TEMP_UNIT_ATTRS(X)			\
+	&dev_attr_temp##X##_input.attr,		\
+	&dev_attr_temp##X##_max.attr,		\
+	&dev_attr_temp##X##_max_hyst.attr
+
+static struct attribute* w83781d_attributes[] = {
+	IN_UNIT_ATTRS(0),
+	IN_UNIT_ATTRS(2),
+	IN_UNIT_ATTRS(3),
+	IN_UNIT_ATTRS(4),
+	IN_UNIT_ATTRS(5),
+	IN_UNIT_ATTRS(6),
+	FAN_UNIT_ATTRS(1),
+	FAN_UNIT_ATTRS(2),
+	FAN_UNIT_ATTRS(3),
+	TEMP_UNIT_ATTRS(1),
+	TEMP_UNIT_ATTRS(2),
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_beep_mask.attr,
+	&dev_attr_beep_enable.attr,
+	NULL
+};
+static const struct attribute_group w83781d_group = {
+	.attrs = w83781d_attributes,
+};
+
+static struct attribute *w83781d_attributes_opt[] = {
+	IN_UNIT_ATTRS(1),
+	IN_UNIT_ATTRS(7),
+	IN_UNIT_ATTRS(8),
+	TEMP_UNIT_ATTRS(3),
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm2.attr,
+	&dev_attr_pwm2_enable.attr,
+	&dev_attr_pwm3.attr,
+	&dev_attr_pwm4.attr,
+	&dev_attr_temp1_type.attr,
+	&dev_attr_temp2_type.attr,
+	&dev_attr_temp3_type.attr,
+	NULL
+};
+static const struct attribute_group w83781d_group_opt = {
+	.attrs = w83781d_attributes_opt,
+};
+
 static int
 w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i = 0, val1 = 0, val2;
-	struct i2c_client *new_client;
+	struct i2c_client *client;
+	struct device *dev;
 	struct w83781d_data *data;
 	int err;
 	const char *client_name = "";
@@ -1075,13 +1082,14 @@
 		goto ERROR1;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
 	mutex_init(&data->lock);
-	new_client->adapter = adapter;
-	new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
-	new_client->flags = 0;
+	client->adapter = adapter;
+	client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
+	client->flags = 0;
+	dev = &client->dev;
 
 	/* Now, we do the remaining detection. */
 
@@ -1090,20 +1098,18 @@
 	   force_*=... parameter, and the Winbond will be reset to the right
 	   bank. */
 	if (kind < 0) {
-		if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80) {
-			dev_dbg(&new_client->dev, "Detection failed at step "
-				"3\n");
+		if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) {
+			dev_dbg(dev, "Detection failed at step 3\n");
 			err = -ENODEV;
 			goto ERROR2;
 		}
-		val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
-		val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+		val1 = w83781d_read_value(client, W83781D_REG_BANK);
+		val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
 		/* Check for Winbond or Asus ID if in bank 0 */
 		if ((!(val1 & 0x07)) &&
 		    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
 		     || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
-			dev_dbg(&new_client->dev, "Detection failed at step "
-				"4\n");
+			dev_dbg(dev, "Detection failed at step 4\n");
 			err = -ENODEV;
 			goto ERROR2;
 		}
@@ -1112,9 +1118,8 @@
 		if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
 				  ((val1 & 0x80) && (val2 == 0x5c)))) {
 			if (w83781d_read_value
-			    (new_client, W83781D_REG_I2C_ADDR) != address) {
-				dev_dbg(&new_client->dev, "Detection failed "
-					"at step 5\n");
+			    (client, W83781D_REG_I2C_ADDR) != address) {
+				dev_dbg(dev, "Detection failed at step 5\n");
 				err = -ENODEV;
 				goto ERROR2;
 			}
@@ -1123,27 +1128,26 @@
 
 	/* We have either had a force parameter, or we have already detected the
 	   Winbond. Put it now into bank 0 and Vendor ID High Byte */
-	w83781d_write_value(new_client, W83781D_REG_BANK,
-			    (w83781d_read_value(new_client,
-						W83781D_REG_BANK) & 0x78) |
-			    0x80);
+	w83781d_write_value(client, W83781D_REG_BANK,
+			    (w83781d_read_value(client, W83781D_REG_BANK)
+			     & 0x78) | 0x80);
 
 	/* Determine the chip type. */
 	if (kind <= 0) {
 		/* get vendor ID */
-		val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+		val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
 		if (val2 == 0x5c)
 			vendid = winbond;
 		else if (val2 == 0x12)
 			vendid = asus;
 		else {
-			dev_dbg(&new_client->dev, "Chip was made by neither "
+			dev_dbg(dev, "Chip was made by neither "
 				"Winbond nor Asus?\n");
 			err = -ENODEV;
 			goto ERROR2;
 		}
 
-		val1 = w83781d_read_value(new_client, W83781D_REG_WCHIPID);
+		val1 = w83781d_read_value(client, W83781D_REG_WCHIPID);
 		if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
 			kind = w83781d;
 		else if (val1 == 0x30 && vendid == winbond)
@@ -1157,7 +1161,7 @@
 			kind = as99127f;
 		else {
 			if (kind == 0)
-				dev_warn(&new_client->dev, "Ignoring 'force' "
+				dev_warn(dev, "Ignoring 'force' "
 					 "parameter for unknown chip at "
 					 "adapter %d, address 0x%02x\n",
 					 i2c_adapter_id(adapter), address);
@@ -1179,20 +1183,20 @@
 	}
 
 	/* Fill in the remaining client fields and put into the global list */
-	strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+	strlcpy(client->name, client_name, I2C_NAME_SIZE);
 	data->type = kind;
 
 	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto ERROR2;
 
 	/* attach secondary i2c lm75-like clients */
 	if (!is_isa) {
 		if ((err = w83781d_detect_subclients(adapter, address,
-				kind, new_client)))
+				kind, client)))
 			goto ERROR3;
 	} else {
 		data->lm75[0] = NULL;
@@ -1200,11 +1204,11 @@
 	}
 
 	/* Initialize the chip */
-	w83781d_init_client(new_client);
+	w83781d_init_client(client);
 
 	/* A few vars need to be filled upon startup */
 	for (i = 1; i <= 3; i++) {
-		data->fan_min[i - 1] = w83781d_read_value(new_client,
+		data->fan_min[i - 1] = w83781d_read_value(client,
 					W83781D_REG_FAN_MIN(i));
 	}
 	if (kind != w83781d && kind != as99127f)
@@ -1212,65 +1216,68 @@
 			data->pwmenable[i] = 1;
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&new_client->dev);
+	if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
+		goto ERROR4;
+
+	if (kind != w83783s) {
+		if ((err = device_create_file(dev, &dev_attr_in1_input))
+		    || (err = device_create_file(dev, &dev_attr_in1_min))
+		    || (err = device_create_file(dev, &dev_attr_in1_max)))
+			goto ERROR4;
+	}
+	if (kind != as99127f && kind != w83781d && kind != w83783s) {
+		if ((err = device_create_file(dev, &dev_attr_in7_input))
+		    || (err = device_create_file(dev, &dev_attr_in7_min))
+		    || (err = device_create_file(dev, &dev_attr_in7_max))
+		    || (err = device_create_file(dev, &dev_attr_in8_input))
+		    || (err = device_create_file(dev, &dev_attr_in8_min))
+		    || (err = device_create_file(dev, &dev_attr_in8_max)))
+			goto ERROR4;
+	}
+	if (kind != w83783s) {
+		if ((err = device_create_file(dev, &dev_attr_temp3_input))
+		    || (err = device_create_file(dev, &dev_attr_temp3_max))
+		    || (err = device_create_file(dev,
+						 &dev_attr_temp3_max_hyst)))
+			goto ERROR4;
+	}
+
+	if (kind != w83781d && kind != as99127f) {
+		if ((err = device_create_file(dev, &dev_attr_pwm1))
+		    || (err = device_create_file(dev, &dev_attr_pwm2))
+		    || (err = device_create_file(dev, &dev_attr_pwm2_enable)))
+			goto ERROR4;
+	}
+	if (kind == w83782d && !is_isa) {
+		if ((err = device_create_file(dev, &dev_attr_pwm3))
+		    || (err = device_create_file(dev, &dev_attr_pwm4)))
+			goto ERROR4;
+	}
+
+	if (kind != as99127f && kind != w83781d) {
+		if ((err = device_create_file(dev, &dev_attr_temp1_type))
+		    || (err = device_create_file(dev,
+						 &dev_attr_temp2_type)))
+			goto ERROR4;
+		if (kind != w83783s) {
+			if ((err = device_create_file(dev,
+						      &dev_attr_temp3_type)))
+				goto ERROR4;
+		}
+	}
+
+	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto ERROR4;
 	}
 
-	device_create_file_in(new_client, 0);
-	if (kind != w83783s)
-		device_create_file_in(new_client, 1);
-	device_create_file_in(new_client, 2);
-	device_create_file_in(new_client, 3);
-	device_create_file_in(new_client, 4);
-	device_create_file_in(new_client, 5);
-	device_create_file_in(new_client, 6);
-	if (kind != as99127f && kind != w83781d && kind != w83783s) {
-		device_create_file_in(new_client, 7);
-		device_create_file_in(new_client, 8);
-	}
-
-	device_create_file_fan(new_client, 1);
-	device_create_file_fan(new_client, 2);
-	device_create_file_fan(new_client, 3);
-
-	device_create_file_temp(new_client, 1);
-	device_create_file_temp(new_client, 2);
-	if (kind != w83783s)
-		device_create_file_temp(new_client, 3);
-
-	device_create_file_vid(new_client);
-	device_create_file_vrm(new_client);
-
-	device_create_file_fan_div(new_client, 1);
-	device_create_file_fan_div(new_client, 2);
-	device_create_file_fan_div(new_client, 3);
-
-	device_create_file_alarms(new_client);
-
-	device_create_file_beep(new_client);
-
-	if (kind != w83781d && kind != as99127f) {
-		device_create_file_pwm(new_client, 1);
-		device_create_file_pwm(new_client, 2);
-		device_create_file_pwmenable(new_client, 2);
-	}
-	if (kind == w83782d && !is_isa) {
-		device_create_file_pwm(new_client, 3);
-		device_create_file_pwm(new_client, 4);
-	}
-
-	if (kind != as99127f && kind != w83781d) {
-		device_create_file_sensor(new_client, 1);
-		device_create_file_sensor(new_client, 2);
-		if (kind != w83783s)
-			device_create_file_sensor(new_client, 3);
-	}
-
 	return 0;
 
 ERROR4:
+	sysfs_remove_group(&dev->kobj, &w83781d_group);
+	sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
+
 	if (data->lm75[1]) {
 		i2c_detach_client(data->lm75[1]);
 		kfree(data->lm75[1]);
@@ -1280,7 +1287,7 @@
 		kfree(data->lm75[0]);
 	}
 ERROR3:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
 ERROR2:
 	kfree(data);
 ERROR1:
@@ -1297,9 +1304,11 @@
 	int err;
 
 	/* main client */
-	if (data)
+	if (data) {
 		hwmon_device_unregister(data->class_dev);
-
+		sysfs_remove_group(&client->dev.kobj, &w83781d_group);
+		sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
+	}
 	if (i2c_is_isa_client(client))
 		release_region(client->addr, W83781D_EXTENT);
 
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index eec43ab..d965d07 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -27,9 +27,9 @@
 
     The w83791d chip appears to be part way between the 83781d and the
     83792d. Thus, this file is derived from both the w83792d.c and
-    w83781d.c files, but its output is more along the lines of the
-    83781d (which means there are no changes to the user-mode sensors
-    program which treats the 83791d as an 83781d).
+    w83781d.c files.
+
+    The w83791g chip is the same as the w83791d but lead-free.
 */
 
 #include <linux/config.h>
@@ -1172,6 +1172,7 @@
 			(w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) +
 			(w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16);
 
+		/* Extract global beep enable flag */
 		data->beep_enable =
 			(data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01;
 
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 7576ec9..4e10826 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -43,6 +43,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
@@ -381,41 +382,6 @@
 store_in_reg(MIN, min);
 store_in_reg(MAX, max);
 
-static struct sensor_device_attribute sda_in_input[] = {
-	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
-	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
-	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
-	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
-	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
-	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
-	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
-	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
-	SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
-};
-static struct sensor_device_attribute sda_in_min[] = {
-       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
-       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
-       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
-       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
-       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
-       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
-       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
-       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
-       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
-};
-static struct sensor_device_attribute sda_in_max[] = {
-       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
-       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
-       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
-       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
-       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
-       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
-       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
-       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
-       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
-};
-
-
 #define show_fan_reg(reg) \
 static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
 			char *buf) \
@@ -499,35 +465,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute sda_fan_input[] = {
-	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1),
-	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2),
-	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3),
-	SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4),
-	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5),
-	SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6),
-	SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7),
-};
-static struct sensor_device_attribute sda_fan_min[] = {
-	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1),
-	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2),
-	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3),
-	SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4),
-	SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5),
-	SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6),
-	SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7),
-};
-static struct sensor_device_attribute sda_fan_div[] = {
-	SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1),
-	SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2),
-	SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3),
-	SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4),
-	SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5),
-	SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6),
-	SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7),
-};
-
-
 /* read/write the temperature1, includes measured value and limits */
 
 static ssize_t show_temp1(struct device *dev, struct device_attribute *attr,
@@ -595,24 +532,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute_2 sda_temp_input[] = {
-	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0),
-	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0),
-	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),
-};
-
-static struct sensor_device_attribute_2 sda_temp_max[] = {
-	SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1),
-	SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2),
-	SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2),
-};
-
-static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
-	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2),
-	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 4),
-	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4),
-};
-
 /* get reatime status of all sensors items: voltage, temp, fan */
 static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -621,9 +540,6 @@
 	return sprintf(buf, "%d\n", data->alarms);
 }
 
-static
-DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-
 static ssize_t
 show_pwm(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -715,21 +631,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute sda_pwm[] = {
-	SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
-	SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
-	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
-};
-static struct sensor_device_attribute sda_pwm_enable[] = {
-	SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
-		    show_pwmenable, store_pwmenable, 1),
-	SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
-		    show_pwmenable, store_pwmenable, 2),
-	SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
-		    show_pwmenable, store_pwmenable, 3),
-};
-
-
 static ssize_t
 show_pwm_mode(struct device *dev, struct device_attribute *attr,
 			char *buf)
@@ -767,16 +668,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute sda_pwm_mode[] = {
-	SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
-		    show_pwm_mode, store_pwm_mode, 0),
-	SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO,
-		    show_pwm_mode, store_pwm_mode, 1),
-	SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO,
-		    show_pwm_mode, store_pwm_mode, 2),
-};
-
-
 static ssize_t
 show_regs_chassis(struct device *dev, struct device_attribute *attr,
 			char *buf)
@@ -785,8 +676,6 @@
 	return sprintf(buf, "%d\n", data->chassis);
 }
 
-static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
-
 static ssize_t
 show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -815,9 +704,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
-		show_chassis_clear, store_chassis_clear);
-
 /* For Smart Fan I / Thermal Cruise */
 static ssize_t
 show_thermal_cruise(struct device *dev, struct device_attribute *attr,
@@ -853,15 +739,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute sda_thermal_cruise[] = {
-	SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO,
-		    show_thermal_cruise, store_thermal_cruise, 1),
-	SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO,
-		    show_thermal_cruise, store_thermal_cruise, 2),
-	SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO,
-		    show_thermal_cruise, store_thermal_cruise, 3),
-};
-
 /* For Smart Fan I/Thermal Cruise and Smart Fan II */
 static ssize_t
 show_tolerance(struct device *dev, struct device_attribute *attr,
@@ -901,15 +778,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute sda_tolerance[] = {
-	SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO,
-		    show_tolerance, store_tolerance, 1),
-	SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO,
-		    show_tolerance, store_tolerance, 2),
-	SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO,
-		    show_tolerance, store_tolerance, 3),
-};
-
 /* For Smart Fan II */
 static ssize_t
 show_sf2_point(struct device *dev, struct device_attribute *attr,
@@ -946,36 +814,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute_2 sda_sf2_point[] = {
-	SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 1, 1),
-	SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 2, 1),
-	SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 3, 1),
-	SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 4, 1),
-
-	SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 1, 2),
-	SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 2, 2),
-	SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 3, 2),
-	SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 4, 2),
-
-	SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 1, 3),
-	SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 2, 3),
-	SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 3, 3),
-	SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR,
-		      show_sf2_point, store_sf2_point, 4, 3),
-};
-
-
 static ssize_t
 show_sf2_level(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -1016,29 +854,6 @@
 	return count;
 }
 
-static struct sensor_device_attribute_2 sda_sf2_level[] = {
-	SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 1, 1),
-	SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 2, 1),
-	SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 3, 1),
-
-	SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 1, 2),
-	SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 2, 2),
-	SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 3, 2),
-
-	SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 1, 3),
-	SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 2, 3),
-	SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR,
-		      show_sf2_level, store_sf2_level, 3, 3),
-};
-
 /* This function is called when:
      * w83792d_driver is inserted (when this module is loaded), for each
        available adapter
@@ -1139,12 +954,297 @@
 	return err;
 }
 
-static void device_create_file_fan(struct device *dev, int 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);
-}
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
+static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 0);
+static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 1);
+static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 2);
+static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 3);
+static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 4);
+static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 5);
+static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 6);
+static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 7);
+static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO,
+			show_in_min, store_in_min, 8);
+static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 0);
+static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 1);
+static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 2);
+static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 3);
+static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 4);
+static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 5);
+static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 6);
+static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 7);
+static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO,
+			show_in_max, store_in_max, 8);
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
+			show_temp1, store_temp1, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23,
+			store_temp23, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23,
+			store_temp23, 1, 2);
+static SENSOR_DEVICE_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR,
+			show_temp1, store_temp1, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR,
+			show_temp23, store_temp23, 0, 4);
+static SENSOR_DEVICE_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR,
+			show_temp23, store_temp23, 1, 4);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
+static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
+			show_chassis_clear, store_chassis_clear);
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
+			show_pwmenable, store_pwmenable, 1);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
+			show_pwmenable, store_pwmenable, 2);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
+			show_pwmenable, store_pwmenable, 3);
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
+			show_pwm_mode, store_pwm_mode, 0);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO,
+			show_pwm_mode, store_pwm_mode, 1);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO,
+			show_pwm_mode, store_pwm_mode, 2);
+static SENSOR_DEVICE_ATTR(tolerance1, S_IWUSR | S_IRUGO,
+			show_tolerance, store_tolerance, 1);
+static SENSOR_DEVICE_ATTR(tolerance2, S_IWUSR | S_IRUGO,
+			show_tolerance, store_tolerance, 2);
+static SENSOR_DEVICE_ATTR(tolerance3, S_IWUSR | S_IRUGO,
+			show_tolerance, store_tolerance, 3);
+static SENSOR_DEVICE_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO,
+			show_thermal_cruise, store_thermal_cruise, 1);
+static SENSOR_DEVICE_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO,
+			show_thermal_cruise, store_thermal_cruise, 2);
+static SENSOR_DEVICE_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO,
+			show_thermal_cruise, store_thermal_cruise, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 1, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 2, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 3, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 4, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 1, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 2, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 3, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 4, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 1, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 2, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 3, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR,
+			show_sf2_point, store_sf2_point, 4, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 1, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 2, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 3, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 1, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 2, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 3, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 1, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 2, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR,
+			show_sf2_level, store_sf2_level, 3, 3);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 3);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 4);
+static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 5);
+static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 6);
+static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 7);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 1);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 2);
+static SENSOR_DEVICE_ATTR(fan3_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 3);
+static SENSOR_DEVICE_ATTR(fan4_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 4);
+static SENSOR_DEVICE_ATTR(fan5_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 5);
+static SENSOR_DEVICE_ATTR(fan6_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 6);
+static SENSOR_DEVICE_ATTR(fan7_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 7);
+
+static struct attribute *w83792d_attributes_fan[4][4] = {
+	{
+		&sensor_dev_attr_fan4_input.dev_attr.attr,
+		&sensor_dev_attr_fan4_min.dev_attr.attr,
+		&sensor_dev_attr_fan4_div.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan5_input.dev_attr.attr,
+		&sensor_dev_attr_fan5_min.dev_attr.attr,
+		&sensor_dev_attr_fan5_div.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan6_input.dev_attr.attr,
+		&sensor_dev_attr_fan6_min.dev_attr.attr,
+		&sensor_dev_attr_fan6_div.dev_attr.attr,
+		NULL
+	}, {
+		&sensor_dev_attr_fan7_input.dev_attr.attr,
+		&sensor_dev_attr_fan7_min.dev_attr.attr,
+		&sensor_dev_attr_fan7_div.dev_attr.attr,
+		NULL
+	}
+};
+
+static const struct attribute_group w83792d_group_fan[4] = {
+	{ .attrs = w83792d_attributes_fan[0] },
+	{ .attrs = w83792d_attributes_fan[1] },
+	{ .attrs = w83792d_attributes_fan[2] },
+	{ .attrs = w83792d_attributes_fan[3] },
+};
+
+static struct attribute *w83792d_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in7_max.dev_attr.attr,
+	&sensor_dev_attr_in7_min.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in8_max.dev_attr.attr,
+	&sensor_dev_attr_in8_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm1_mode.dev_attr.attr,
+	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm2_mode.dev_attr.attr,
+	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
+	&sensor_dev_attr_pwm3_mode.dev_attr.attr,
+	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_chassis.attr,
+	&dev_attr_chassis_clear.attr,
+	&sensor_dev_attr_tolerance1.dev_attr.attr,
+	&sensor_dev_attr_thermal_cruise1.dev_attr.attr,
+	&sensor_dev_attr_tolerance2.dev_attr.attr,
+	&sensor_dev_attr_thermal_cruise2.dev_attr.attr,
+	&sensor_dev_attr_tolerance3.dev_attr.attr,
+	&sensor_dev_attr_thermal_cruise3.dev_attr.attr,
+	&sensor_dev_attr_sf2_point1_fan1.dev_attr.attr,
+	&sensor_dev_attr_sf2_point2_fan1.dev_attr.attr,
+	&sensor_dev_attr_sf2_point3_fan1.dev_attr.attr,
+	&sensor_dev_attr_sf2_point4_fan1.dev_attr.attr,
+	&sensor_dev_attr_sf2_point1_fan2.dev_attr.attr,
+	&sensor_dev_attr_sf2_point2_fan2.dev_attr.attr,
+	&sensor_dev_attr_sf2_point3_fan2.dev_attr.attr,
+	&sensor_dev_attr_sf2_point4_fan2.dev_attr.attr,
+	&sensor_dev_attr_sf2_point1_fan3.dev_attr.attr,
+	&sensor_dev_attr_sf2_point2_fan3.dev_attr.attr,
+	&sensor_dev_attr_sf2_point3_fan3.dev_attr.attr,
+	&sensor_dev_attr_sf2_point4_fan3.dev_attr.attr,
+	&sensor_dev_attr_sf2_level1_fan1.dev_attr.attr,
+	&sensor_dev_attr_sf2_level2_fan1.dev_attr.attr,
+	&sensor_dev_attr_sf2_level3_fan1.dev_attr.attr,
+	&sensor_dev_attr_sf2_level1_fan2.dev_attr.attr,
+	&sensor_dev_attr_sf2_level2_fan2.dev_attr.attr,
+	&sensor_dev_attr_sf2_level3_fan2.dev_attr.attr,
+	&sensor_dev_attr_sf2_level1_fan3.dev_attr.attr,
+	&sensor_dev_attr_sf2_level2_fan3.dev_attr.attr,
+	&sensor_dev_attr_sf2_level3_fan3.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_div.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group w83792d_group = {
+	.attrs = w83792d_attributes,
+};
 
 static int
 w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -1268,59 +1368,46 @@
 	}
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
+	if ((err = sysfs_create_group(&dev->kobj, &w83792d_group)))
 		goto ERROR3;
-	}
-	for (i = 0; i < 9; i++) {
-		device_create_file(dev, &sda_in_input[i].dev_attr);
-		device_create_file(dev, &sda_in_max[i].dev_attr);
-		device_create_file(dev, &sda_in_min[i].dev_attr);
-	}
-	for (i = 0; i < 3; i++)
-		device_create_file_fan(dev, i);
 
 	/* Read GPIO enable register to check if pins for fan 4,5 are used as
 	   GPIO */
 	val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN);
+
 	if (!(val1 & 0x40))
-		device_create_file_fan(dev, 3);
+		if ((err = sysfs_create_group(&dev->kobj,
+					      &w83792d_group_fan[0])))
+			goto exit_remove_files;
+
 	if (!(val1 & 0x20))
-		device_create_file_fan(dev, 4);
+		if ((err = sysfs_create_group(&dev->kobj,
+					      &w83792d_group_fan[1])))
+			goto exit_remove_files;
 
 	val1 = w83792d_read_value(client, W83792D_REG_PIN);
 	if (val1 & 0x40)
-		device_create_file_fan(dev, 5);
+		if ((err = sysfs_create_group(&dev->kobj,
+					      &w83792d_group_fan[2])))
+			goto exit_remove_files;
+
 	if (val1 & 0x04)
-		device_create_file_fan(dev, 6);
+		if ((err = sysfs_create_group(&dev->kobj,
+					      &w83792d_group_fan[3])))
+			goto exit_remove_files;
 
-	for (i = 0; i < 3; 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, &sda_thermal_cruise[i].dev_attr);
-		device_create_file(dev, &sda_tolerance[i].dev_attr);
+	data->class_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove_files;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) {
-		device_create_file(dev, &sda_pwm[i].dev_attr);
-		device_create_file(dev, &sda_pwm_enable[i].dev_attr);
-		device_create_file(dev, &sda_pwm_mode[i].dev_attr);
-	}
-
-	device_create_file(dev, &dev_attr_alarms);
-	device_create_file(dev, &dev_attr_chassis);
-	device_create_file(dev, &dev_attr_chassis_clear);
-
-	for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++)
-		device_create_file(dev, &sda_sf2_point[i].dev_attr);
-
-	for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++)
-		device_create_file(dev, &sda_sf2_level[i].dev_attr);
-
 	return 0;
 
+exit_remove_files:
+	sysfs_remove_group(&dev->kobj, &w83792d_group);
+	for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++)
+		sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]);
 ERROR3:
 	if (data->lm75[0] != NULL) {
 		i2c_detach_client(data->lm75[0]);
@@ -1342,11 +1429,16 @@
 w83792d_detach_client(struct i2c_client *client)
 {
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	int err;
+	int err, i;
 
 	/* main client */
-	if (data)
+	if (data) {
 		hwmon_device_unregister(data->class_dev);
+		sysfs_remove_group(&client->dev.kobj, &w83792d_group);
+		for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++)
+			sysfs_remove_group(&client->dev.kobj,
+					   &w83792d_group_fan[i]);
+	}
 
 	if ((err = i2c_detach_client(client)))
 		return err;
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 3f2bac1..a3fcace 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -236,21 +236,30 @@
 	 * Nothing yet, assume it is already started.
 	 */
 
+	err = device_create_file(&new_client->dev,
+				 &sensor_dev_attr_temp1_input.dev_attr);
+	if (err)
+		goto exit_remove;
+
+	err = device_create_file(&new_client->dev,
+				 &sensor_dev_attr_temp1_max.dev_attr);
+	if (err)
+		goto exit_remove;
+
 	/* Register sysfs hooks */
 	data->class_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
-		goto exit_detach;
+		goto exit_remove;
 	}
 
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_input.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp1_max.dev_attr);
-
 	return 0;
 
-exit_detach:
+exit_remove:
+	device_remove_file(&new_client->dev,
+			   &sensor_dev_attr_temp1_input.dev_attr);
+	device_remove_file(&new_client->dev,
+			   &sensor_dev_attr_temp1_max.dev_attr);
 	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
@@ -264,7 +273,10 @@
 	int err;
 
 	hwmon_device_unregister(data->class_dev);
-
+	device_remove_file(&client->dev,
+			   &sensor_dev_attr_temp1_input.dev_attr);
+	device_remove_file(&client->dev,
+			   &sensor_dev_attr_temp1_max.dev_attr);
 	if ((err = i2c_detach_client(client)))
 		return err;
 
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 9e56c39..0d96679 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -196,7 +196,7 @@
 
 config I2C_IOP3XX
 	tristate "Intel IOP3xx and IXP4xx on-chip I2C interface"
-	depends on (ARCH_IOP3XX || ARCH_IXP4XX) && I2C
+	depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX) && I2C
 	help
 	  Say Y here if you want to use the IIC bus controller on
 	  the Intel IOP3xx I/O Processors or IXP4xx Network Processors.
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 8e41315..4436c89 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -82,14 +82,16 @@
 
 	/* 
 	 * Every time unit enable is asserted, GPOD needs to be cleared
-	 * on IOP321 to avoid data corruption on the bus.
+	 * on IOP3XX to avoid data corruption on the bus.
 	 */
-#ifdef CONFIG_ARCH_IOP321
-#define IOP321_GPOD_I2C0    0x00c0  /* clear these bits to enable ch0 */
-#define IOP321_GPOD_I2C1    0x0030  /* clear these bits to enable ch1 */
-
-	*IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 : 
-		~IOP321_GPOD_I2C1;
+#ifdef CONFIG_PLAT_IOP
+	if (iop3xx_adap->id == 0) {
+		gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
+		gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
+	} else {
+		gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW);
+		gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW);
+	}
 #endif
 	/* NB SR bits not same position as CR IE bits :-( */
 	iop3xx_adap->SR_enabled = 
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 8f2b1f0..0ca599d 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -210,8 +210,8 @@
 
 static void __exit i2c_sibyte_exit(void)
 {
-	i2c_del_bus(&sibyte_board_adapter[0]);
-	i2c_del_bus(&sibyte_board_adapter[1]);
+	i2c_del_adapter(&sibyte_board_adapter[0]);
+	i2c_del_adapter(&sibyte_board_adapter[1]);
 }
 
 module_init(i2c_sibyte_init);
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index f92505b..182f049 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -30,7 +30,7 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 #include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index a574de5..d55b938 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -318,6 +318,20 @@
 	hwif->drives[0].autodma = hwif->autodma;
 }
 
+static void __devinit init_hwif_sb600_legacy(ide_hwif_t *hwif)
+{
+
+	hwif->atapi_dma = 1;
+	hwif->ultra_mask = 0x7f;
+	hwif->mwdma_mask = 0x07;
+	hwif->swdma_mask = 0x07;
+
+	if (!noautodma)
+		hwif->autodma = 1;
+	hwif->drives[0].autodma = hwif->autodma;
+	hwif->drives[1].autodma = hwif->autodma;
+}
+
 static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
 	{	/* 0 */
 		.name		= "ATIIXP",
@@ -326,6 +340,12 @@
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
 		.bootable	= ON_BOARD,
+	},{	/* 1 */
+		.name		= "ATI SB600 SATA Legacy IDE",
+		.init_hwif	= init_hwif_sb600_legacy,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.bootable	= ON_BOARD,
 	}
 };
 
@@ -348,6 +368,7 @@
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, PCI_ANY_ID, PCI_ANY_ID, (PCI_CLASS_STORAGE_IDE<<8)|0x8a, 0xffff05, 1},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 9cbf09e..60d3fbd 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -86,7 +86,7 @@
 int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
 {
 	struct net_device *dev;
-	u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+	__be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
 	int ret;
 
 	dev = ip_dev_find(ip);
@@ -239,7 +239,7 @@
 {
 	struct net_device *dev;
 	u32 src_ip = src_in->sin_addr.s_addr;
-	u32 dst_ip = dst_in->sin_addr.s_addr;
+	__be32 dst_ip = dst_in->sin_addr.s_addr;
 	int ret;
 
 	dev = ip_dev_find(dst_ip);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a9dda56..83eac3a 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -183,4 +183,13 @@
 	  This driver implements support for HIL-keyboards attached
 	  to your machine, so normally you should say Y here.
 
+config KEYBOARD_OMAP
+	tristate "TI OMAP keypad support"
+	depends on (ARCH_OMAP1 || ARCH_OMAP2)
+	help
+	  Say Y here if you want to use the OMAP keypad.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called omap-keypad.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 2708167..b265391 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -15,4 +15,5 @@
 obj-$(CONFIG_KEYBOARD_SPITZ)		+= spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
+obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o
 
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
new file mode 100644
index 0000000..d436287
--- /dev/null
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -0,0 +1,492 @@
+/*
+ * linux/drivers/input/keyboard/omap-keypad.c
+ *
+ * OMAP Keypad Driver
+ *
+ * Copyright (C) 2003 Nokia Corporation
+ * Written by Timo Teräs <ext-timo.teras@nokia.com>
+ *
+ * Added support for H2 & H3 Keypad
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/menelaus.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/arch/mux.h>
+
+#undef NEW_BOARD_LEARNING_MODE
+
+static void omap_kp_tasklet(unsigned long);
+static void omap_kp_timer(unsigned long);
+
+static unsigned char keypad_state[8];
+static DEFINE_MUTEX(kp_enable_mutex);
+static int kp_enable = 1;
+static int kp_cur_group = -1;
+
+struct omap_kp {
+	struct input_dev *input;
+	struct timer_list timer;
+	int irq;
+	unsigned int rows;
+	unsigned int cols;
+	unsigned long delay;
+	unsigned int debounce;
+};
+
+DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
+
+static int *keymap;
+static unsigned int *row_gpios;
+static unsigned int *col_gpios;
+
+#ifdef CONFIG_ARCH_OMAP2
+static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value)
+{
+	int col;
+	for (col = 0; col < omap_kp->cols; col++) {
+		if (value & (1 << col))
+			omap_set_gpio_dataout(col_gpios[col], 1);
+		else
+			omap_set_gpio_dataout(col_gpios[col], 0);
+	}
+}
+
+static u8 get_row_gpio_val(struct omap_kp *omap_kp)
+{
+	int row;
+	u8 value = 0;
+
+	for (row = 0; row < omap_kp->rows; row++) {
+		if (omap_get_gpio_datain(row_gpios[row]))
+			value |= (1 << row);
+	}
+	return value;
+}
+#else
+#define		set_col_gpio_val(x, y)	do {} while (0)
+#define		get_row_gpio_val(x)	0
+#endif
+
+static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
+				     struct pt_regs *regs)
+{
+	struct omap_kp *omap_kp = dev_id;
+
+	/* disable keyboard interrupt and schedule for handling */
+	if (cpu_is_omap24xx()) {
+		int i;
+		for (i = 0; i < omap_kp->rows; i++)
+			disable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
+	} else
+		/* disable keyboard interrupt and schedule for handling */
+		omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+	tasklet_schedule(&kp_tasklet);
+
+	return IRQ_HANDLED;
+}
+
+static void omap_kp_timer(unsigned long data)
+{
+	tasklet_schedule(&kp_tasklet);
+}
+
+static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
+{
+	int col = 0;
+
+	/* read the keypad status */
+	if (cpu_is_omap24xx()) {
+		int i;
+		for (i = 0; i < omap_kp->rows; i++)
+			disable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
+
+		/* read the keypad status */
+		for (col = 0; col < omap_kp->cols; col++) {
+			set_col_gpio_val(omap_kp, ~(1 << col));
+			state[col] = ~(get_row_gpio_val(omap_kp)) & 0x3f;
+		}
+		set_col_gpio_val(omap_kp, 0);
+
+	} else {
+		/* disable keyboard interrupt and schedule for handling */
+		omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+		/* read the keypad status */
+		omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+		for (col = 0; col < omap_kp->cols; col++) {
+			omap_writew(~(1 << col) & 0xff,
+				    OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+
+			udelay(omap_kp->delay);
+
+			state[col] = ~omap_readw(OMAP_MPUIO_BASE +
+						 OMAP_MPUIO_KBR_LATCH) & 0xff;
+		}
+		omap_writew(0x00, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+		udelay(2);
+	}
+}
+
+static inline int omap_kp_find_key(int col, int row)
+{
+	int i, key;
+
+	key = KEY(col, row, 0);
+	for (i = 0; keymap[i] != 0; i++)
+		if ((keymap[i] & 0xff000000) == key)
+			return keymap[i] & 0x00ffffff;
+	return -1;
+}
+
+static void omap_kp_tasklet(unsigned long data)
+{
+	struct omap_kp *omap_kp_data = (struct omap_kp *) data;
+	unsigned char new_state[8], changed, key_down = 0;
+	int col, row;
+	int spurious = 0;
+
+	/* check for any changes */
+	omap_kp_scan_keypad(omap_kp_data, new_state);
+
+	/* check for changes and print those */
+	for (col = 0; col < omap_kp_data->cols; col++) {
+		changed = new_state[col] ^ keypad_state[col];
+		key_down |= new_state[col];
+		if (changed == 0)
+			continue;
+
+		for (row = 0; row < omap_kp_data->rows; row++) {
+			int key;
+			if (!(changed & (1 << row)))
+				continue;
+#ifdef NEW_BOARD_LEARNING_MODE
+			printk(KERN_INFO "omap-keypad: key %d-%d %s\n", col,
+			       row, (new_state[col] & (1 << row)) ?
+			       "pressed" : "released");
+#else
+			key = omap_kp_find_key(col, row);
+			if (key < 0) {
+				printk(KERN_WARNING
+				      "omap-keypad: Spurious key event %d-%d\n",
+				       col, row);
+				/* We scan again after a couple of seconds */
+				spurious = 1;
+				continue;
+			}
+
+			if (!(kp_cur_group == (key & GROUP_MASK) ||
+			      kp_cur_group == -1))
+				continue;
+
+			kp_cur_group = key & GROUP_MASK;
+			input_report_key(omap_kp_data->input, key & ~GROUP_MASK,
+					 new_state[col] & (1 << row));
+#endif
+		}
+	}
+	memcpy(keypad_state, new_state, sizeof(keypad_state));
+
+	if (key_down) {
+                int delay = HZ / 20;
+		/* some key is pressed - keep irq disabled and use timer
+		 * to poll the keypad */
+		if (spurious)
+			delay = 2 * HZ;
+		mod_timer(&omap_kp_data->timer, jiffies + delay);
+	} else {
+		/* enable interrupts */
+		if (cpu_is_omap24xx()) {
+			int i;
+			for (i = 0; i < omap_kp_data->rows; i++)
+				enable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
+		} else {
+			omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+			kp_cur_group = -1;
+		}
+ 	}
+}
+
+static ssize_t omap_kp_enable_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", kp_enable);
+}
+
+static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	int state;
+
+	if (sscanf(buf, "%u", &state) != 1)
+		return -EINVAL;
+
+	if ((state != 1) && (state != 0))
+		return -EINVAL;
+
+	mutex_lock(&kp_enable_mutex);
+	if (state != kp_enable) {
+		if (state)
+			enable_irq(INT_KEYBOARD);
+		else
+			disable_irq(INT_KEYBOARD);
+		kp_enable = state;
+	}
+	mutex_unlock(&kp_enable_mutex);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, omap_kp_enable_show, omap_kp_enable_store);
+
+#ifdef CONFIG_PM
+static int omap_kp_suspend(struct platform_device *dev, pm_message_t state)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+
+static int omap_kp_resume(struct platform_device *dev)
+{
+	/* Nothing yet */
+
+	return 0;
+}
+#else
+#define omap_kp_suspend	NULL
+#define omap_kp_resume	NULL
+#endif
+
+static int __init omap_kp_probe(struct platform_device *pdev)
+{
+	struct omap_kp *omap_kp;
+	struct input_dev *input_dev;
+	struct omap_kp_platform_data *pdata =  pdev->dev.platform_data;
+	int i, col_idx, row_idx, irq_idx, ret;
+
+	if (!pdata->rows || !pdata->cols || !pdata->keymap) {
+		printk(KERN_ERR "No rows, cols or keymap from pdata\n");
+		return -EINVAL;
+	}
+
+	omap_kp = kzalloc(sizeof(struct omap_kp), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!omap_kp || !input_dev) {
+		kfree(omap_kp);
+		input_free_device(input_dev);
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, omap_kp);
+
+	omap_kp->input = input_dev;
+
+	/* Disable the interrupt for the MPUIO keyboard */
+	if (!cpu_is_omap24xx())
+		omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+	keymap = pdata->keymap;
+
+	if (pdata->rep)
+		set_bit(EV_REP, input_dev->evbit);
+
+	if (pdata->delay)
+		omap_kp->delay = pdata->delay;
+
+	if (pdata->row_gpios && pdata->col_gpios) {
+		row_gpios = pdata->row_gpios;
+		col_gpios = pdata->col_gpios;
+	}
+
+	omap_kp->rows = pdata->rows;
+	omap_kp->cols = pdata->cols;
+
+	if (cpu_is_omap24xx()) {
+		/* Cols: outputs */
+		for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
+			if (omap_request_gpio(col_gpios[col_idx]) < 0) {
+				printk(KERN_ERR "Failed to request"
+				       "GPIO%d for keypad\n",
+				       col_gpios[col_idx]);
+				goto err1;
+			}
+			omap_set_gpio_direction(col_gpios[col_idx], 0);
+		}
+		/* Rows: inputs */
+		for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
+			if (omap_request_gpio(row_gpios[row_idx]) < 0) {
+				printk(KERN_ERR "Failed to request"
+				       "GPIO%d for keypad\n",
+				       row_gpios[row_idx]);
+				goto err2;
+			}
+			omap_set_gpio_direction(row_gpios[row_idx], 1);
+		}
+	}
+
+	setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
+
+	/* get the irq and init timer*/
+	tasklet_enable(&kp_tasklet);
+	kp_tasklet.data = (unsigned long) omap_kp;
+
+	ret = device_create_file(&pdev->dev, &dev_attr_enable);
+	if (ret < 0)
+		goto err2;
+
+	/* setup input device */
+	set_bit(EV_KEY, input_dev->evbit);
+	for (i = 0; keymap[i] != 0; i++)
+		set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
+	input_dev->name = "omap-keypad";
+	input_dev->phys = "omap-keypad/input0";
+	input_dev->cdev.dev = &pdev->dev;
+	input_dev->private = omap_kp;
+
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+
+	input_dev->keycode = keymap;
+	input_dev->keycodesize = sizeof(unsigned int);
+	input_dev->keycodemax = pdata->keymapsize;
+
+	ret = input_register_device(omap_kp->input);
+	if (ret < 0) {
+		printk(KERN_ERR "Unable to register omap-keypad input device\n");
+		goto err3;
+	}
+
+	if (pdata->dbounce)
+		omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
+
+	/* scan current status and enable interrupt */
+	omap_kp_scan_keypad(omap_kp, keypad_state);
+	if (!cpu_is_omap24xx()) {
+		omap_kp->irq = platform_get_irq(pdev, 0);
+		if (omap_kp->irq >= 0) {
+			if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
+					"omap-keypad", omap_kp) < 0)
+				goto err4;
+		}
+		omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+	} else {
+		for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
+			if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]),
+				       	omap_kp_interrupt,
+					IRQF_TRIGGER_FALLING,
+				       	"omap-keypad", omap_kp) < 0)
+				goto err5;
+		}
+	}
+	return 0;
+err5:
+	for (i = irq_idx-1; i >=0; i--)
+		free_irq(row_gpios[i], 0);
+err4:
+	input_unregister_device(omap_kp->input);
+	input_dev = NULL;
+err3:
+	device_remove_file(&pdev->dev, &dev_attr_enable);
+err2:
+	for (i = row_idx-1; i >=0; i--)
+		omap_free_gpio(row_gpios[i]);
+err1:
+	for (i = col_idx-1; i >=0; i--)
+		omap_free_gpio(col_gpios[i]);
+
+	kfree(omap_kp);
+	input_free_device(input_dev);
+
+	return -EINVAL;
+}
+
+static int omap_kp_remove(struct platform_device *pdev)
+{
+	struct omap_kp *omap_kp = platform_get_drvdata(pdev);
+
+	/* disable keypad interrupt handling */
+	tasklet_disable(&kp_tasklet);
+	if (cpu_is_omap24xx()) {
+		int i;
+		for (i = 0; i < omap_kp->cols; i++)
+	    		omap_free_gpio(col_gpios[i]);
+		for (i = 0; i < omap_kp->rows; i++) {
+	    		omap_free_gpio(row_gpios[i]);
+			free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0);
+		}
+	} else {
+		omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+		free_irq(omap_kp->irq, 0);
+	}
+
+	del_timer_sync(&omap_kp->timer);
+	tasklet_kill(&kp_tasklet);
+
+	/* unregister everything */
+	input_unregister_device(omap_kp->input);
+
+	kfree(omap_kp);
+
+	return 0;
+}
+
+static struct platform_driver omap_kp_driver = {
+	.probe		= omap_kp_probe,
+	.remove		= omap_kp_remove,
+	.suspend	= omap_kp_suspend,
+	.resume		= omap_kp_resume,
+	.driver		= {
+		.name	= "omap-keypad",
+	},
+};
+
+static int __devinit omap_kp_init(void)
+{
+	printk(KERN_INFO "OMAP Keypad Driver\n");
+	return platform_driver_register(&omap_kp_driver);
+}
+
+static void __exit omap_kp_exit(void)
+{
+	platform_driver_unregister(&omap_kp_driver);
+}
+
+module_init(omap_kp_init);
+module_exit(omap_kp_exit);
+
+MODULE_AUTHOR("Timo Teräs");
+MODULE_DESCRIPTION("OMAP Keypad Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 3845def..5cfbe6a 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -192,7 +192,7 @@
 		return "bit stuffing error, timeout, or unknown USB error";
 	case -EILSEQ:
 		return "CRC mismatch, timeout, or unknown USB error";
-	case -ETIMEDOUT:
+	case -ETIME:
 		return "timed out";
 	case -EPIPE:
 		return "endpoint stalled";
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
index ec52c1a..6349367 100644
--- a/drivers/isdn/hisax/hfc_usb.h
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -137,11 +137,11 @@
 	{-ENXIO, "URB already queued"},
 	{-EFBIG, "Too much ISO frames requested"},
 	{-ENOSR, "Buffer error (overrun)"},
-	{-EPIPE, "Specified endpoint is stalled (device not responding)"},
+	{-EPIPE, "Specified endpoint is stalled"},
 	{-EOVERFLOW, "Babble (bad cable?)"},
 	{-EPROTO, "Bit-stuff error (bad cable?)"},
-	{-EILSEQ, "CRC/Timeout"},
-	{-ETIMEDOUT, "NAK (device does not respond)"},
+	{-EILSEQ, "CRC or missing token"},
+	{-ETIME, "Device did not respond"},
 	{-ESHUTDOWN, "Device unplugged"},
 	{-1, NULL}
 };
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 43da8ae..1f8d6ae6 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1614,8 +1614,8 @@
 	struct sk_buff *skb;
 	unsigned char *p;
 	struct in_device *in_dev = NULL;
-	u32 addr = 0;		/* local ipv4 address */
-	u32 mask = 0;		/* local netmask */
+	__be32 addr = 0;		/* local ipv4 address */
+	__be32 mask = 0;		/* local netmask */
 
 	if ((in_dev = lp->netdev->dev.ip_ptr) != NULL) {
 		/* take primary(first) address of interface */
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c
index 713c4a8..45ba3d4 100644
--- a/drivers/leds/leds-net48xx.c
+++ b/drivers/leds/leds-net48xx.c
@@ -16,6 +16,7 @@
 #include <linux/leds.h>
 #include <linux/err.h>
 #include <asm/io.h>
+#include <linux/nsc_gpio.h>
 #include <linux/scx200_gpio.h>
 
 #define DRVNAME "net48xx-led"
@@ -26,10 +27,7 @@
 static void net48xx_error_led_set(struct led_classdev *led_cdev,
 		enum led_brightness value)
 {
-	if (value)
-		scx200_gpio_set_high(NET48XX_ERROR_LED_GPIO);
-	else
-		scx200_gpio_set_low(NET48XX_ERROR_LED_GPIO);
+	scx200_gpio_ops.gpio_set(NET48XX_ERROR_LED_GPIO, value ? 1 : 0);
 }
 
 static struct led_classdev net48xx_error_led = {
@@ -81,7 +79,8 @@
 {
 	int ret;
 
-	if (!scx200_gpio_present()) {
+	/* small hack, but scx200_gpio doesn't set .dev if the probe fails */
+	if (!scx200_gpio_ops.dev) {
 		ret = -ENODEV;
 		goto out;
 	}
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index a82f313..6c29fe7 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -16,7 +16,7 @@
 #define MAX_PMU_LEVEL 0xFF
 
 static struct backlight_properties pmu_backlight_data;
-static spinlock_t pmu_backlight_lock;
+static DEFINE_SPINLOCK(pmu_backlight_lock);
 static int sleeping;
 static u8 bl_curve[FB_BACKLIGHT_LEVELS];
 
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index aceb61d..83f79de 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -397,12 +397,7 @@
 
 static int __init sat_sensors_init(void)
 {
-	int err;
-
-	err = i2c_add_driver(&wf_sat_driver);
-	if (err < 0)
-		return err;
-	return 0;
+	return i2c_add_driver(&wf_sat_driver);
 }
 
 static void __exit sat_sensors_exit(void)
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index 9002f35..88b2837 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -80,7 +80,6 @@
 
 	switch (urb->status) {
 		case 0:         /* success */
-		case -ETIMEDOUT:    /* NAK */
 			break;
 		case -ECONNRESET:   /* kill */
 		case -ENOENT:
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 6c1cb77..c9d66354 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -215,7 +215,7 @@
 		case -ECONNRESET:
 		case -ENOENT:
 		case -ESHUTDOWN:
-		case -ETIMEDOUT:
+		case -ETIME:
 			/* this urb is dead, cleanup */
 			dprintk("%s:urb shutting down with status: %d\n",
 					__FUNCTION__, urb->status);
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 1b07a61..5d8cd28 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -301,10 +301,11 @@
 static struct symbolic_list urb_errlist[] = {
 	{ -ENOSR,	"Buffer error (overrun)" },
 	{ -EPIPE,	"Stalled (device not responding)" },
-	{ -EOVERFLOW,	"Babble (bad cable?)" },
+	{ -EOVERFLOW,	"Babble (device sends too much data)" },
 	{ -EPROTO,	"Bit-stuff error (bad cable?)" },
-	{ -EILSEQ,	"CRC/Timeout" },
-	{ -ETIMEDOUT,	"NAK (device does not respond)" },
+	{ -EILSEQ,	"CRC/Timeout (bad cable?)" },
+	{ -ETIME,	"Device does not respond to token" },
+	{ -ETIMEDOUT,	"Device does not respond to command" },
 	{ -1, NULL }
 };
 
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index d470394..53c4b57 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -711,7 +711,7 @@
 			case -EOVERFLOW:	errmsg = "Babble (bad cable?)"; break;
 			case -EPROTO:		errmsg = "Bit-stuff error (bad cable?)"; break;
 			case -EILSEQ:		errmsg = "CRC/Timeout (could be anything)"; break;
-			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
+			case -ETIME:		errmsg = "Device does not respond"; break;
 		}
 		PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
 		/* Give up after a number of contiguous errors on the USB bus.
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 20f211b..2912326 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -586,15 +586,14 @@
 	{ -EFBIG,     "Too much ISO frames requested" },
 	{ -ENOSR,     "Buffer error (overrun)" },
 	{ -EPIPE,     "Specified endpoint is stalled (device not responding)"},
-	{ -EOVERFLOW, "Babble (bad cable?)" },
+	{ -EOVERFLOW, "Babble (too much data)" },
 	{ -EPROTO,    "Bit-stuff error (bad cable?)" },
 	{ -EILSEQ,    "CRC/Timeout" },
-	{ -ETIMEDOUT, "NAK (device does not respond)" },
+	{ -ETIME,     "Device does not respond to token" },
+	{ -ETIMEDOUT, "Device does not respond to command" },
 	{ -1, NULL }
 };
 
-
-
 /****************************************************************************
  * Memory management functions                                              *
  ****************************************************************************/
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 0277681..82938ad 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -58,6 +58,7 @@
 static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
 {
 	struct input_dev *idev = ts->idev;
+
 	input_report_abs(idev, ABS_X, x);
 	input_report_abs(idev, ABS_Y, y);
 	input_report_abs(idev, ABS_PRESSURE, pressure);
@@ -67,6 +68,7 @@
 static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
 {
 	struct input_dev *idev = ts->idev;
+
 	input_report_abs(idev, ABS_PRESSURE, 0);
 	input_sync(idev);
 }
@@ -189,6 +191,7 @@
 static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
 {
 	unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
+
 	if (machine_is_collie())
 		return (!(val & (UCB_TS_CR_TSPX_LOW)));
 	else
@@ -291,6 +294,7 @@
 static void ucb1x00_ts_irq(int idx, void *id)
 {
 	struct ucb1x00_ts *ts = id;
+
 	ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
 	wake_up(&ts->irq_wait);
 }
@@ -372,36 +376,43 @@
 static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
 {
 	struct ucb1x00_ts *ts;
+	struct input_dev *idev;
+	int err;
 
 	ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
-	if (!ts)
-		return -ENOMEM;
-
-	ts->idev = input_allocate_device();
-	if (!ts->idev) {
-		kfree(ts);
-		return -ENOMEM;
+	idev = input_allocate_device();
+	if (!ts || !idev) {
+		err = -ENOMEM;
+		goto fail;
 	}
 
 	ts->ucb = dev->ucb;
+	ts->idev = idev;
 	ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
 
-	ts->idev->private = ts;
-	ts->idev->name       = "Touchscreen panel";
-	ts->idev->id.product = ts->ucb->id;
-	ts->idev->open       = ucb1x00_ts_open;
-	ts->idev->close      = ucb1x00_ts_close;
+	idev->private    = ts;
+	idev->name       = "Touchscreen panel";
+	idev->id.product = ts->ucb->id;
+	idev->open       = ucb1x00_ts_open;
+	idev->close      = ucb1x00_ts_close;
 
-	__set_bit(EV_ABS, ts->idev->evbit);
-	__set_bit(ABS_X, ts->idev->absbit);
-	__set_bit(ABS_Y, ts->idev->absbit);
-	__set_bit(ABS_PRESSURE, ts->idev->absbit);
+	__set_bit(EV_ABS, idev->evbit);
+	__set_bit(ABS_X, idev->absbit);
+	__set_bit(ABS_Y, idev->absbit);
+	__set_bit(ABS_PRESSURE, idev->absbit);
 
-	input_register_device(ts->idev);
+	err = input_register_device(idev);
+	if (err)
+		goto fail;
 
 	dev->priv = ts;
 
 	return 0;
+
+ fail:
+	input_free_device(idev);
+	kfree(ts);
+	return err;
 }
 
 static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 6b7638b..cb142a6 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -822,6 +822,7 @@
 	mmc->f_min = 375000;
 	mmc->f_max = 25000000;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_BYTEBLOCK;
 
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
@@ -850,7 +851,7 @@
 	/*
 	 * Allocate the MCI interrupt
 	 */
-	ret = request_irq(AT91_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+	ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
 	if (ret) {
 		printk(KERN_ERR "Failed to request MCI interrupt\n");
 		clk_disable(mci_clk);
@@ -906,7 +907,7 @@
 
 	mmc_remove_host(mmc);
 	at91_mci_disable();
-	free_irq(AT91_ID_MCI, host);
+	free_irq(AT91RM9200_ID_MCI, host);
 	mmc_free_host(mmc);
 
 	clk_disable(mci_clk);				/* Disable the peripheral clock */
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index fb6565b..1b79dd2 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -956,7 +956,7 @@
 	mmc->f_min = 150000;
 	mmc->f_max = CLK_RATE/2;
 	mmc->ocr_avail = MMC_VDD_32_33;
-	mmc->caps |= MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_BYTEBLOCK;
 
 	/* MMC core transfer sizes tunable parameters */
 	mmc->max_hw_segs = 64;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 74eaaee..5b9caa7 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -996,7 +996,6 @@
 
 		mmc_set_data_timeout(&data, card, 0);
 
-		data.blksz_bits = 3;
 		data.blksz = 1 << 3;
 		data.blocks = 1;
 		data.flags = MMC_DATA_READ;
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index a0e0dad..db0e8ad 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -32,6 +32,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -165,6 +166,7 @@
 	do {
 		struct mmc_blk_request brq;
 		struct mmc_command cmd;
+		u32 readcmd, writecmd;
 
 		memset(&brq, 0, sizeof(struct mmc_blk_request));
 		brq.mrq.cmd = &brq.cmd;
@@ -172,7 +174,6 @@
 
 		brq.cmd.arg = req->sector << 9;
 		brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-		brq.data.blksz_bits = md->block_bits;
 		brq.data.blksz = 1 << md->block_bits;
 		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
@@ -181,20 +182,31 @@
 
 		mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
 
-		if (rq_data_dir(req) == READ) {
-			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
-			brq.data.flags |= MMC_DATA_READ;
-		} else {
-			brq.cmd.opcode = MMC_WRITE_BLOCK;
-			brq.data.flags |= MMC_DATA_WRITE;
+		/*
+		 * If the host doesn't support multiple block writes, force
+		 * block writes to single block.
+		 */
+		if (rq_data_dir(req) != READ &&
+		    !(card->host->caps & MMC_CAP_MULTIWRITE))
 			brq.data.blocks = 1;
-		}
 
 		if (brq.data.blocks > 1) {
 			brq.data.flags |= MMC_DATA_MULTI;
 			brq.mrq.stop = &brq.stop;
+			readcmd = MMC_READ_MULTIPLE_BLOCK;
+			writecmd = MMC_WRITE_MULTIPLE_BLOCK;
 		} else {
 			brq.mrq.stop = NULL;
+			readcmd = MMC_READ_SINGLE_BLOCK;
+			writecmd = MMC_WRITE_BLOCK;
+		}
+
+		if (rq_data_dir(req) == READ) {
+			brq.cmd.opcode = readcmd;
+			brq.data.flags |= MMC_DATA_READ;
+		} else {
+			brq.cmd.opcode = writecmd;
+			brq.data.flags |= MMC_DATA_WRITE;
 		}
 
 		brq.data.sg = mq->sg;
@@ -219,27 +231,29 @@
 			goto cmd_err;
 		}
 
-		do {
-			int err;
+		if (rq_data_dir(req) != READ) {
+			do {
+				int err;
 
-			cmd.opcode = MMC_SEND_STATUS;
-			cmd.arg = card->rca << 16;
-			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-			err = mmc_wait_for_cmd(card->host, &cmd, 5);
-			if (err) {
-				printk(KERN_ERR "%s: error %d requesting status\n",
-				       req->rq_disk->disk_name, err);
-				goto cmd_err;
-			}
-		} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+				cmd.opcode = MMC_SEND_STATUS;
+				cmd.arg = card->rca << 16;
+				cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+				err = mmc_wait_for_cmd(card->host, &cmd, 5);
+				if (err) {
+					printk(KERN_ERR "%s: error %d requesting status\n",
+					       req->rq_disk->disk_name, err);
+					goto cmd_err;
+				}
+			} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
 
 #if 0
-		if (cmd.resp[0] & ~0x00000900)
-			printk(KERN_ERR "%s: status = %08x\n",
-			       req->rq_disk->disk_name, cmd.resp[0]);
-		if (mmc_decode_status(cmd.resp))
-			goto cmd_err;
+			if (cmd.resp[0] & ~0x00000900)
+				printk(KERN_ERR "%s: status = %08x\n",
+				       req->rq_disk->disk_name, cmd.resp[0]);
+			if (mmc_decode_status(cmd.resp))
+				goto cmd_err;
 #endif
+		}
 
 		/*
 		 * A block was successfully transferred.
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 1886562..2b5a0cc 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -69,12 +69,13 @@
 	unsigned int datactrl, timeout, irqmask;
 	unsigned long long clks;
 	void __iomem *base;
+	int blksz_bits;
 
 	DBG(host, "blksz %04x blks %04x flags %08x\n",
-	    1 << data->blksz_bits, data->blocks, data->flags);
+	    data->blksz, data->blocks, data->flags);
 
 	host->data = data;
-	host->size = data->blocks << data->blksz_bits;
+	host->size = data->blksz;
 	host->data_xfered = 0;
 
 	mmci_init_sg(host, data);
@@ -88,7 +89,10 @@
 	writel(timeout, base + MMCIDATATIMER);
 	writel(host->size, base + MMCIDATALENGTH);
 
-	datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4;
+	blksz_bits = ffs(data->blksz) - 1;
+	BUG_ON(1 << blksz_bits != data->blksz);
+
+	datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
 	if (data->flags & MMC_DATA_READ) {
 		datactrl |= MCI_DPSM_DIRECTION;
 		irqmask = MCI_RXFIFOHALFFULLMASK;
@@ -145,7 +149,7 @@
 	      unsigned int status)
 {
 	if (status & MCI_DATABLOCKEND) {
-		host->data_xfered += 1 << data->blksz_bits;
+		host->data_xfered += data->blksz;
 	}
 	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
 		if (status & MCI_DATACRCFAIL)
@@ -505,6 +509,7 @@
 	mmc->f_min = (host->mclk + 511) / 512;
 	mmc->f_max = min(host->mclk, fmax);
 	mmc->ocr_avail = plat->ocr_mask;
+	mmc->caps = MMC_CAP_MULTIWRITE;
 
 	/*
 	 * We can do SGIO
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index ddf06b3..52c9e52 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -1034,13 +1034,14 @@
 	host->irq = pdev->resource[1].start;
 	host->base = (void __iomem*)IO_ADDRESS(r->start);
 
-	if (minfo->wire4)
-		 mmc->caps |= MMC_CAP_4_BIT_DATA;
-
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;
 	mmc->f_max = 24000000;
 	mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_BYTEBLOCK;
+
+	if (minfo->wire4)
+		 mmc->caps |= MMC_CAP_4_BIT_DATA;
 
 	/* Use scatterlist DMA to reduce per-transfer costs.
 	 * NOTE max_seg_size assumption that small blocks aren't
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 4e21b3b..fdfc383 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -1262,7 +1262,7 @@
 	mmc->ops = &sdhci_ops;
 	mmc->f_min = host->max_clk / 256;
 	mmc->f_max = host->max_clk;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
 	mmc->ocr_avail = 0;
 	if (caps & SDHCI_CAN_VDD_330)
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index c351c6d..6435a68 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1323,7 +1323,7 @@
 	mmc->f_min = 375000;
 	mmc->f_max = 24000000;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
 	spin_lock_init(&host->lock);
 
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 5b6b05e..9d34056 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -299,7 +299,7 @@
 	 *	Slow phase with lock held.
 	 */
 
-	disable_irq_nosync_lockdep(dev->irq);
+	disable_irq_nosync_lockdep_irqsave(dev->irq, &flags);
 
 	spin_lock(&ei_local->page_lock);
 
@@ -338,7 +338,7 @@
 		netif_stop_queue(dev);
 		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 		spin_unlock(&ei_local->page_lock);
-		enable_irq_lockdep(dev->irq);
+		enable_irq_lockdep_irqrestore(dev->irq, &flags);
 		ei_local->stat.tx_errors++;
 		return 1;
 	}
@@ -379,7 +379,7 @@
 	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 
 	spin_unlock(&ei_local->page_lock);
-	enable_irq_lockdep(dev->irq);
+	enable_irq_lockdep_irqrestore(dev->irq, &flags);
 
 	dev_kfree_skb (skb);
 	ei_local->stat.tx_bytes += send_length;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6315477..ff8a8c0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -24,6 +24,9 @@
 
 	  If unsure, say Y.
 
+# All the following symbols are dependent on NETDEVICES - do not repeat
+# that for each of the symbols.
+if NETDEVICES
 
 config IFB
 	tristate "Intermediate Functional Block support"
@@ -2852,6 +2855,8 @@
 	If you want to log kernel messages over the network, enable this.
 	See <file:Documentation/networking/netconsole.txt> for details.
 
+endif #NETDEVICES
+
 config NETPOLL
 	def_bool NETCONSOLE
 
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index a075246..71a4f60 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -163,11 +163,7 @@
 #define SET_NETDEV_DEV(net, pdev)	do{} while(0)
 #endif
 
-#if LINUX_VERSION_CODE >= 0x2051c
 #define ace_sync_irq(irq)	synchronize_irq(irq)
-#else
-#define ace_sync_irq(irq)	synchronize_irq()
-#endif
 
 #ifndef offset_in_page
 #define offset_in_page(ptr)	((unsigned long)(ptr) & ~PAGE_MASK)
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 7f7dd45..b98592a 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -145,9 +145,7 @@
 
 	/* Create the Extended DDP header */
 	ddp = (struct ddpehdr *)skb->data;
-        ddp->deh_len = skb->len;
-        ddp->deh_hops = 1;
-        ddp->deh_pad = 0;
+        ddp->deh_len_hops = htons(skb->len + (1<<10));
         ddp->deh_sum = 0;
 
 	/*
@@ -170,7 +168,6 @@
         ddp->deh_sport = 72;
 
         *((__u8 *)(ddp+1)) = 22;        	/* ddp type = IP */
-        *((__u16 *)ddp)=ntohs(*((__u16 *)ddp));	/* fix up length field */
 
         skb->protocol = htons(ETH_P_ATALK);     /* Protocol has changed */
 
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 95b28aa..3ecf2cc5 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -947,7 +947,7 @@
 		return -ENOMEM;
 
 	dev->base_addr = AT91_VA_BASE_EMAC;
-	dev->irq = AT91_ID_EMAC;
+	dev->irq = AT91RM9200_ID_EMAC;
 	SET_MODULE_OWNER(dev);
 
 	/* Install the interrupt handler */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6a40707..3fb354d 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -85,6 +85,7 @@
 #define     AD_LINK_SPEED_BITMASK_10MBPS      0x2
 #define     AD_LINK_SPEED_BITMASK_100MBPS     0x4
 #define     AD_LINK_SPEED_BITMASK_1000MBPS    0x8
+#define     AD_LINK_SPEED_BITMASK_10000MBPS   0x10
 //endalloun
 
 // compare MAC addresses
@@ -99,7 +100,7 @@
 static u8 __get_duplex(struct port *port);
 static inline void __initialize_port_locks(struct port *port);
 //conversions
-static void __ntohs_lacpdu(struct lacpdu *lacpdu);
+static void __htons_lacpdu(struct lacpdu *lacpdu);
 static u16 __ad_timer_to_ticks(u16 timer_type, u16 Par);
 
 
@@ -330,7 +331,8 @@
  *     0,
  *     %AD_LINK_SPEED_BITMASK_10MBPS,
  *     %AD_LINK_SPEED_BITMASK_100MBPS,
- *     %AD_LINK_SPEED_BITMASK_1000MBPS
+ *     %AD_LINK_SPEED_BITMASK_1000MBPS,
+ *     %AD_LINK_SPEED_BITMASK_10000MBPS
  */
 static u16 __get_link_speed(struct port *port)
 {
@@ -357,6 +359,10 @@
 			speed = AD_LINK_SPEED_BITMASK_1000MBPS;
 			break;
 
+		case SPEED_10000:
+			speed = AD_LINK_SPEED_BITMASK_10000MBPS;
+			break;
+
 		default:
 			speed = 0; // unknown speed value from ethtool. shouldn't happen
 			break;
@@ -414,23 +420,23 @@
 
 //conversions
 /**
- * __ntohs_lacpdu - convert the contents of a LACPDU to host byte order
+ * __htons_lacpdu - convert the contents of a LACPDU to network byte order
  * @lacpdu: the speicifed lacpdu
  *
  * For each multi-byte field in the lacpdu, convert its content
  */
-static void __ntohs_lacpdu(struct lacpdu *lacpdu)
+static void __htons_lacpdu(struct lacpdu *lacpdu)
 {
 	if (lacpdu) {
-		lacpdu->actor_system_priority =   ntohs(lacpdu->actor_system_priority);
-		lacpdu->actor_key =               ntohs(lacpdu->actor_key);
-		lacpdu->actor_port_priority =     ntohs(lacpdu->actor_port_priority);
-		lacpdu->actor_port =              ntohs(lacpdu->actor_port);
-		lacpdu->partner_system_priority = ntohs(lacpdu->partner_system_priority);
-		lacpdu->partner_key =             ntohs(lacpdu->partner_key);
-		lacpdu->partner_port_priority =   ntohs(lacpdu->partner_port_priority);
-		lacpdu->partner_port =            ntohs(lacpdu->partner_port);
-		lacpdu->collector_max_delay =     ntohs(lacpdu->collector_max_delay);
+		lacpdu->actor_system_priority =   htons(lacpdu->actor_system_priority);
+		lacpdu->actor_key =               htons(lacpdu->actor_key);
+		lacpdu->actor_port_priority =     htons(lacpdu->actor_port_priority);
+		lacpdu->actor_port =              htons(lacpdu->actor_port);
+		lacpdu->partner_system_priority = htons(lacpdu->partner_system_priority);
+		lacpdu->partner_key =             htons(lacpdu->partner_key);
+		lacpdu->partner_port_priority =   htons(lacpdu->partner_port_priority);
+		lacpdu->partner_port =            htons(lacpdu->partner_port);
+		lacpdu->collector_max_delay =     htons(lacpdu->collector_max_delay);
 	}
 }
 
@@ -490,11 +496,11 @@
 	// validate lacpdu and port
 	if (lacpdu && port) {
 		// record the new parameter values for the partner operational
-		port->partner_oper_port_number = lacpdu->actor_port;
-		port->partner_oper_port_priority = lacpdu->actor_port_priority;
+		port->partner_oper_port_number = ntohs(lacpdu->actor_port);
+		port->partner_oper_port_priority = ntohs(lacpdu->actor_port_priority);
 		port->partner_oper_system = lacpdu->actor_system;
-		port->partner_oper_system_priority = lacpdu->actor_system_priority;
-		port->partner_oper_key = lacpdu->actor_key;
+		port->partner_oper_system_priority = ntohs(lacpdu->actor_system_priority);
+		port->partner_oper_key = ntohs(lacpdu->actor_key);
 		// zero partener's lase states
 		port->partner_oper_port_state = 0;
 		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_ACTIVITY);
@@ -561,11 +567,11 @@
 	// validate lacpdu and port
 	if (lacpdu && port) {
 		// check if any parameter is different
-		if ((lacpdu->actor_port != port->partner_oper_port_number) ||
-		    (lacpdu->actor_port_priority != port->partner_oper_port_priority) ||
+		if ((ntohs(lacpdu->actor_port) != port->partner_oper_port_number) ||
+		    (ntohs(lacpdu->actor_port_priority) != port->partner_oper_port_priority) ||
 		    MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->partner_oper_system)) ||
-		    (lacpdu->actor_system_priority != port->partner_oper_system_priority) ||
-		    (lacpdu->actor_key != port->partner_oper_key) ||
+		    (ntohs(lacpdu->actor_system_priority) != port->partner_oper_system_priority) ||
+		    (ntohs(lacpdu->actor_key) != port->partner_oper_key) ||
 		    ((lacpdu->actor_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
 		   ) {
 			// update the state machine Selected variable
@@ -628,11 +634,11 @@
 	// validate lacpdu and port
 	if (lacpdu && port) {
 		// check if all parameters are alike
-		if (((lacpdu->partner_port == port->actor_port_number) &&
-		     (lacpdu->partner_port_priority == port->actor_port_priority) &&
+		if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
+		     (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
 		     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
-		     (lacpdu->partner_system_priority == port->actor_system_priority) &&
-		     (lacpdu->partner_key == port->actor_oper_port_key) &&
+		     (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
+		     (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
 		     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
 		    // or this is individual link(aggregation == FALSE)
 		    ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
@@ -662,11 +668,11 @@
 	// validate lacpdu and port
 	if (lacpdu && port) {
 		// check if any parameter is different
-		if ((lacpdu->partner_port != port->actor_port_number) ||
-		    (lacpdu->partner_port_priority != port->actor_port_priority) ||
+		if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
+		    (ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
 		    MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
-		    (lacpdu->partner_system_priority != port->actor_system_priority) ||
-		    (lacpdu->partner_key != port->actor_oper_port_key) ||
+		    (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
+		    (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
 		    ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
 		    ((lacpdu->partner_state & AD_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)) ||
 		    ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
@@ -775,6 +781,9 @@
 		case AD_LINK_SPEED_BITMASK_1000MBPS:
 			bandwidth = aggregator->num_of_ports * 1000;
 			break;
+		case AD_LINK_SPEED_BITMASK_10000MBPS:
+			bandwidth = aggregator->num_of_ports * 10000;
+			break;
 		default:
 			bandwidth=0; // to silent the compilor ....
 		}
@@ -847,7 +856,7 @@
 	 */
 
 	/* Convert all non u8 parameters to Big Endian for transmit */
-	__ntohs_lacpdu(lacpdu);
+	__htons_lacpdu(lacpdu);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -2171,7 +2180,6 @@
 
 		switch (lacpdu->subtype) {
 		case AD_TYPE_LACPDU:
-			__ntohs_lacpdu(lacpdu);
 			dprintk("Received LACPDU on port %d\n", port->actor_port_number);
 			ad_rx_machine(lacpdu, port);
 			break;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 850aae2..c0bbdda 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -96,6 +96,7 @@
 static char *xmit_hash_policy = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+static char *arp_validate = NULL;
 struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
@@ -127,6 +128,8 @@
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
 module_param_array(arp_ip_target, charp, NULL, 0);
 MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
+module_param(arp_validate, charp, 0);
+MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
 
 /*----------------------------- Global variables ----------------------------*/
 
@@ -170,6 +173,14 @@
 {	NULL,			-1},
 };
 
+struct bond_parm_tbl arp_validate_tbl[] = {
+{	"none",			BOND_ARP_VALIDATE_NONE},
+{	"active",		BOND_ARP_VALIDATE_ACTIVE},
+{	"backup",		BOND_ARP_VALIDATE_BACKUP},
+{	"all",			BOND_ARP_VALIDATE_ALL},
+{	NULL,			-1},
+};
+
 /*-------------------------- Forward declarations ---------------------------*/
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
@@ -638,6 +649,7 @@
 	case SPEED_10:
 	case SPEED_100:
 	case SPEED_1000:
+	case SPEED_10000:
 		break;
 	default:
 		return -1;
@@ -1210,10 +1222,14 @@
 	unsigned long features = BOND_INTERSECT_FEATURES;
 	struct slave *slave;
 	struct net_device *bond_dev = bond->dev;
+	unsigned short max_hard_header_len = ETH_HLEN;
 	int i;
 
-	bond_for_each_slave(bond, slave, i)
+	bond_for_each_slave(bond, slave, i) {
 		features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
+		if (slave->dev->hard_header_len > max_hard_header_len)
+			max_hard_header_len = slave->dev->hard_header_len;
+	}
 
 	if ((features & NETIF_F_SG) && 
 	    !(features & NETIF_F_ALL_CSUM))
@@ -1231,6 +1247,7 @@
 
 	features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
 	bond_dev->features = features;
+	bond_dev->hard_header_len = max_hard_header_len;
 
 	return 0;
 }
@@ -1365,6 +1382,7 @@
 	}
 
 	new_slave->dev = slave_dev;
+	slave_dev->priv_flags |= IFF_BONDING;
 
 	if ((bond->params.mode == BOND_MODE_TLB) ||
 	    (bond->params.mode == BOND_MODE_ALB)) {
@@ -1417,6 +1435,8 @@
 
 	bond_compute_features(bond);
 
+	new_slave->last_arp_rx = jiffies;
+
 	if (bond->params.miimon && !bond->params.use_carrier) {
 		link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
@@ -1493,29 +1513,8 @@
 
 	switch (bond->params.mode) {
 	case BOND_MODE_ACTIVEBACKUP:
-		/* if we're in active-backup mode, we need one and
-		 * only one active interface. The backup interfaces
-		 * will have their SLAVE_INACTIVE flag set because we
-		 * need them to be drop all packets. Thus, since we
-		 * guarantee that curr_active_slave always point to
-		 * the last usable interface, we just have to verify
-		 * this interface's flag.
-		 */
-		if (((!bond->curr_active_slave) ||
-		     (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
-		    (new_slave->link != BOND_LINK_DOWN)) {
-			/* first slave or no active slave yet, and this link
-			   is OK, so make this interface the active one */
-			bond_change_active_slave(bond, new_slave);
-			printk(KERN_INFO DRV_NAME
-			       ": %s: first active interface up!\n",
-			       bond->dev->name);
-			netif_carrier_on(bond->dev);
-
-		} else {
-			dprintk("This is just a backup slave\n");
-			bond_set_slave_inactive_flags(new_slave);
-		}
+		bond_set_slave_inactive_flags(new_slave);
+		bond_select_active_slave(bond);
 		break;
 	case BOND_MODE_8023AD:
 		/* in 802.3ad mode, the internal mechanism
@@ -1778,7 +1777,8 @@
 	dev_set_mac_address(slave_dev, &addr);
 
 	slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-				   IFF_SLAVE_INACTIVE);
+				   IFF_SLAVE_INACTIVE | IFF_BONDING |
+				   IFF_SLAVE_NEEDARP);
 
 	kfree(slave);
 
@@ -2252,7 +2252,7 @@
 {
 	struct in_device *idev;
 	struct in_ifaddr *ifa;
-	u32 addr = 0;
+	__be32 addr = 0;
 
 	if (!dev)
 		return 0;
@@ -2291,6 +2291,25 @@
 	return 0;
 }
 
+static int bond_has_this_ip(struct bonding *bond, u32 ip)
+{
+	struct vlan_entry *vlan, *vlan_next;
+
+	if (ip == bond->master_ip)
+		return 1;
+
+	if (list_empty(&bond->vlan_list))
+		return 0;
+
+	list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
+				 vlan_list) {
+		if (ip == vlan->vlan_ip)
+			return 1;
+	}
+
+	return 0;
+}
+
 /*
  * We go to the (large) trouble of VLAN tagging ARP frames because
  * switches in VLAN mode (especially if ports are configured as
@@ -2429,6 +2448,93 @@
 	}
 }
 
+static void bond_validate_arp(struct bonding *bond, struct slave *slave, u32 sip, u32 tip)
+{
+	int i;
+	u32 *targets = bond->params.arp_targets;
+
+	targets = bond->params.arp_targets;
+	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+		dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] "
+			"%u.%u.%u.%u bhti(tip) %d\n",
+		       NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]),
+		       bond_has_this_ip(bond, tip));
+		if (sip == targets[i]) {
+			if (bond_has_this_ip(bond, tip))
+				slave->last_arp_rx = jiffies;
+			return;
+		}
+	}
+}
+
+static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+{
+	struct arphdr *arp;
+	struct slave *slave;
+	struct bonding *bond;
+	unsigned char *arp_ptr;
+	u32 sip, tip;
+
+	if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
+		goto out;
+
+	bond = dev->priv;
+	read_lock(&bond->lock);
+
+	dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n",
+		bond->dev->name, skb->dev ? skb->dev->name : "NULL",
+		orig_dev ? orig_dev->name : "NULL");
+
+	slave = bond_get_slave_by_dev(bond, orig_dev);
+	if (!slave || !slave_do_arp_validate(bond, slave))
+		goto out_unlock;
+
+	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
+	if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+				 (2 * dev->addr_len) +
+				 (2 * sizeof(u32)))))
+		goto out_unlock;
+
+	arp = skb->nh.arph;
+	if (arp->ar_hln != dev->addr_len ||
+	    skb->pkt_type == PACKET_OTHERHOST ||
+	    skb->pkt_type == PACKET_LOOPBACK ||
+	    arp->ar_hrd != htons(ARPHRD_ETHER) ||
+	    arp->ar_pro != htons(ETH_P_IP) ||
+	    arp->ar_pln != 4)
+		goto out_unlock;
+
+	arp_ptr = (unsigned char *)(arp + 1);
+	arp_ptr += dev->addr_len;
+	memcpy(&sip, arp_ptr, 4);
+	arp_ptr += 4 + dev->addr_len;
+	memcpy(&tip, arp_ptr, 4);
+
+	dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u"
+		" tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name,
+		slave->state, bond->params.arp_validate,
+		slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip));
+
+	/*
+	 * Backup slaves won't see the ARP reply, but do come through
+	 * here for each ARP probe (so we swap the sip/tip to validate
+	 * the probe).  In a "redundant switch, common router" type of
+	 * configuration, the ARP probe will (hopefully) travel from
+	 * the active, through one switch, the router, then the other
+	 * switch before reaching the backup.
+	 */
+	if (slave->state == BOND_STATE_ACTIVE)
+		bond_validate_arp(bond, slave, sip, tip);
+	else
+		bond_validate_arp(bond, slave, tip, sip);
+
+out_unlock:
+	read_unlock(&bond->lock);
+out:
+	dev_kfree_skb(skb);
+	return NET_RX_SUCCESS;
+}
+
 /*
  * this function is called regularly to monitor each slave's link
  * ensuring that traffic is being sent and received when arp monitoring
@@ -2593,7 +2699,8 @@
 	 */
 	bond_for_each_slave(bond, slave, i) {
 		if (slave->link != BOND_LINK_UP) {
-			if ((jiffies - slave->dev->last_rx) <= delta_in_ticks) {
+			if ((jiffies - slave_last_rx(bond, slave)) <=
+			     delta_in_ticks) {
 
 				slave->link = BOND_LINK_UP;
 
@@ -2638,7 +2745,7 @@
 
 			if ((slave != bond->curr_active_slave) &&
 			    (!bond->current_arp_slave) &&
-			    (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) &&
+			    (((jiffies - slave_last_rx(bond, slave)) >= 3*delta_in_ticks) &&
 			     bond_has_ip(bond))) {
 				/* a backup slave has gone down; three times
 				 * the delta allows the current slave to be
@@ -2685,7 +2792,7 @@
 		 * if it is up and needs to take over as the curr_active_slave
 		 */
 		if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
-	    (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
+	    (((jiffies - slave_last_rx(bond, slave)) >= (2*delta_in_ticks)) &&
 	     bond_has_ip(bond))) &&
 		    ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) {
 
@@ -2950,7 +3057,7 @@
 	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
 	seq_printf(seq, "MII Status: %s\n",
 		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-	seq_printf(seq, "Link Failure Count: %d\n",
+	seq_printf(seq, "Link Failure Count: %u\n",
 		   slave->link_failure_count);
 
 	seq_printf(seq,
@@ -3210,6 +3317,9 @@
 		(event_dev ? event_dev->name : "None"),
 		event);
 
+	if (!(event_dev->priv_flags & IFF_BONDING))
+		return NOTIFY_DONE;
+
 	if (event_dev->flags & IFF_MASTER) {
 		dprintk("IFF_MASTER\n");
 		return bond_master_netdev_event(event, event_dev);
@@ -3305,6 +3415,21 @@
 	dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
 }
 
+void bond_register_arp(struct bonding *bond)
+{
+	struct packet_type *pt = &bond->arp_mon_pt;
+
+	pt->type = htons(ETH_P_ARP);
+	pt->dev = NULL; /*bond->dev;XXX*/
+	pt->func = bond_arp_rcv;
+	dev_add_pack(pt);
+}
+
+void bond_unregister_arp(struct bonding *bond)
+{
+	dev_remove_pack(&bond->arp_mon_pt);
+}
+
 /*---------------------------- Hashing Policies -----------------------------*/
 
 /*
@@ -3391,6 +3516,9 @@
 		} else {
 			arp_timer->function = (void *)&bond_loadbalance_arp_mon;
 		}
+		if (bond->params.arp_validate)
+			bond_register_arp(bond);
+
 		add_timer(arp_timer);
 	}
 
@@ -3418,9 +3546,11 @@
 		bond_unregister_lacpdu(bond);
 	}
 
+	if (bond->params.arp_validate)
+		bond_unregister_arp(bond);
+
 	write_lock_bh(&bond->lock);
 
-	bond_mc_list_destroy(bond);
 
 	/* signal timers not to re-arm */
 	bond->kill_timers = 1;
@@ -3451,8 +3581,6 @@
 		break;
 	}
 
-	/* Release the bonded slaves */
-	bond_release_all(bond_dev);
 
 	if ((bond->params.mode == BOND_MODE_TLB) ||
 	    (bond->params.mode == BOND_MODE_ALB)) {
@@ -4179,6 +4307,7 @@
 	/* Initialize the device options */
 	bond_dev->tx_queue_len = 0;
 	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
+	bond_dev->priv_flags |= IFF_BONDING;
 
 	/* At first, we block adding VLANs. That's the only way to
 	 * prevent problems that occur when adding VLANs over an
@@ -4237,6 +4366,9 @@
 	list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
 		struct net_device *bond_dev = bond->dev;
 
+		bond_mc_list_destroy(bond);
+		/* Release the bonded slaves */
+		bond_release_all(bond_dev);
 		unregister_netdevice(bond_dev);
 		bond_deinit(bond_dev);
 	}
@@ -4270,6 +4402,8 @@
 
 static int bond_check_params(struct bond_params *params)
 {
+	int arp_validate_value;
+
 	/*
 	 * Convert string parameters.
 	 */
@@ -4473,6 +4607,29 @@
 		arp_interval = 0;
 	}
 
+	if (arp_validate) {
+		if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+			printk(KERN_ERR DRV_NAME
+	       ": arp_validate only supported in active-backup mode\n");
+			return -EINVAL;
+		}
+		if (!arp_interval) {
+			printk(KERN_ERR DRV_NAME
+			       ": arp_validate requires arp_interval\n");
+			return -EINVAL;
+		}
+
+		arp_validate_value = bond_parse_parm(arp_validate,
+						     arp_validate_tbl);
+		if (arp_validate_value == -1) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: invalid arp_validate \"%s\"\n",
+			       arp_validate == NULL ? "NULL" : arp_validate);
+			return -EINVAL;
+		}
+	} else
+		arp_validate_value = 0;
+
 	if (miimon) {
 		printk(KERN_INFO DRV_NAME
 		       ": MII link monitoring set to %d ms\n",
@@ -4481,8 +4638,10 @@
 		int i;
 
 		printk(KERN_INFO DRV_NAME
-		       ": ARP monitoring set to %d ms with %d target(s):",
-		       arp_interval, arp_ip_count);
+		       ": ARP monitoring set to %d ms, validate %s, with %d target(s):",
+		       arp_interval,
+		       arp_validate_tbl[arp_validate_value].modename,
+		       arp_ip_count);
 
 		for (i = 0; i < arp_ip_count; i++)
 			printk (" %s", arp_ip_target[i]);
@@ -4516,6 +4675,7 @@
 	params->xmit_policy = xmit_hashtype;
 	params->miimon = miimon;
 	params->arp_interval = arp_interval;
+	params->arp_validate = arp_validate_value;
 	params->updelay = updelay;
 	params->downdelay = downdelay;
 	params->use_carrier = use_carrier;
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index cfe4dc3..ced9ed8 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -51,6 +51,7 @@
 extern struct bond_parm_tbl bond_mode_tbl[];
 extern struct bond_parm_tbl bond_lacp_tbl[];
 extern struct bond_parm_tbl xmit_hashtype_tbl[];
+extern struct bond_parm_tbl arp_validate_tbl[];
 
 static int expected_refcount = -1;
 static struct class *netdev_class;
@@ -503,6 +504,53 @@
 static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
 
 /*
+ * Show and set arp_validate.
+ */
+static ssize_t bonding_show_arp_validate(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%s %d\n",
+		       arp_validate_tbl[bond->params.arp_validate].modename,
+		       bond->params.arp_validate) + 1;
+}
+
+static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value;
+	struct bonding *bond = to_bond(cd);
+
+	new_value = bond_parse_parm((char *)buf, arp_validate_tbl);
+	if (new_value < 0) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Ignoring invalid arp_validate value %s\n",
+		       bond->dev->name, buf);
+		return -EINVAL;
+	}
+	if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: arp_validate only supported in active-backup mode.\n",
+		       bond->dev->name);
+		return -EINVAL;
+	}
+	printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
+	       bond->dev->name, arp_validate_tbl[new_value].modename,
+	       new_value);
+
+	if (!bond->params.arp_validate && new_value) {
+		bond_register_arp(bond);
+	} else if (bond->params.arp_validate && !new_value) {
+		bond_unregister_arp(bond);
+	}
+
+	bond->params.arp_validate = new_value;
+
+	return count;
+}
+
+static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
+
+/*
  * Show and set the arp timer interval.  There are two tricky bits
  * here.  First, if ARP monitoring is activated, then we must disable
  * MII monitoring.  Second, if the ARP timer isn't running, we must
@@ -914,6 +962,11 @@
 			       "ARP monitoring. Disabling ARP monitoring...\n",
 			       bond->dev->name);
 			bond->params.arp_interval = 0;
+			if (bond->params.arp_validate) {
+				bond_unregister_arp(bond);
+				bond->params.arp_validate =
+					BOND_ARP_VALIDATE_NONE;
+			}
 			/* Kill ARP timer, else it brings bond's link down */
 			if (bond->mii_timer.function) {
 				printk(KERN_INFO DRV_NAME
@@ -1093,7 +1146,7 @@
 			     strlen(slave->dev->name)) == 0) {
         			old_active = bond->curr_active_slave;
         			new_active = slave;
-        			if (new_active && (new_active == old_active)) {
+        			if (new_active == old_active) {
 					/* do nothing */
 					printk(KERN_INFO DRV_NAME
 				       	       ": %s: %s is already the current active slave.\n",
@@ -1273,6 +1326,7 @@
 static struct attribute *per_bond_attrs[] = {
 	&class_device_attr_slaves.attr,
 	&class_device_attr_mode.attr,
+	&class_device_attr_arp_validate.attr,
 	&class_device_attr_arp_interval.attr,
 	&class_device_attr_arp_ip_target.attr,
 	&class_device_attr_downdelay.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 0bdfe2c..dc434fb 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,8 +22,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"3.0.3"
-#define DRV_RELDATE	"March 23, 2006"
+#define DRV_VERSION	"3.1.1"
+#define DRV_RELDATE	"September 26, 2006"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
@@ -126,6 +126,7 @@
 	int xmit_policy;
 	int miimon;
 	int arp_interval;
+	int arp_validate;
 	int use_carrier;
 	int updelay;
 	int downdelay;
@@ -149,8 +150,9 @@
 	struct net_device *dev; /* first - useful for panic debug */
 	struct slave *next;
 	struct slave *prev;
-	s16    delay;
+	int    delay;
 	u32    jiffies;
+	u32    last_arp_rx;
 	s8     link;    /* one of BOND_LINK_XXXX */
 	s8     state;   /* one of BOND_STATE_XXXX */
 	u32    original_flags;
@@ -198,6 +200,7 @@
 	struct   bond_params params;
 	struct   list_head vlan_list;
 	struct   vlan_group *vlgrp;
+	struct   packet_type arp_mon_pt;
 };
 
 /**
@@ -228,6 +231,25 @@
 	return (struct bonding *)slave->dev->master->priv;
 }
 
+#define BOND_ARP_VALIDATE_NONE		0
+#define BOND_ARP_VALIDATE_ACTIVE	(1 << BOND_STATE_ACTIVE)
+#define BOND_ARP_VALIDATE_BACKUP	(1 << BOND_STATE_BACKUP)
+#define BOND_ARP_VALIDATE_ALL		(BOND_ARP_VALIDATE_ACTIVE | \
+					 BOND_ARP_VALIDATE_BACKUP)
+
+extern inline int slave_do_arp_validate(struct bonding *bond, struct slave *slave)
+{
+	return bond->params.arp_validate & (1 << slave->state);
+}
+
+extern inline u32 slave_last_rx(struct bonding *bond, struct slave *slave)
+{
+	if (slave_do_arp_validate(bond, slave))
+		return slave->last_arp_rx;
+
+	return slave->dev->last_rx;
+}
+
 static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
 	struct bonding *bond = slave->dev->master->priv;
@@ -235,12 +257,14 @@
 	    bond->params.mode != BOND_MODE_ALB)
 		slave->state = BOND_STATE_BACKUP;
 	slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
+	if (slave_do_arp_validate(bond, slave))
+		slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
 }
 
 static inline void bond_set_slave_active_flags(struct slave *slave)
 {
 	slave->state = BOND_STATE_ACTIVE;
-	slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
+	slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
 }
 
 static inline void bond_set_master_3ad_flags(struct bonding *bond)
@@ -284,6 +308,8 @@
 const char *bond_mode_name(int mode);
 void bond_select_active_slave(struct bonding *bond);
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
+void bond_register_arp(struct bonding *);
+void bond_unregister_arp(struct bonding *);
 
 #endif /* _LINUX_BONDING_H */
 
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index a170e96..4020acb 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -1367,8 +1367,8 @@
 
 /* Structure containing variables used by the shared code (e1000_hw.c) */
 struct e1000_hw {
-    uint8_t *hw_addr;
-    uint8_t *flash_address;
+    uint8_t __iomem *hw_addr;
+    uint8_t __iomem *flash_address;
     e1000_mac_type mac_type;
     e1000_phy_type phy_type;
     uint32_t phy_init_script;
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index 22ac2df..e17a144 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -30,6 +30,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/8xx_immap.h>
 #include <asm/pgtable.h>
@@ -37,7 +38,6 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/commproc.h>
-#include <asm/dma-mapping.h>
 
 #include "fec_8xx.h"
 
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 97db910..eea1d66 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -3789,6 +3789,12 @@
 	/* setup packet for tx */
 	pkt_len = ETH_DATA_LEN;
 	tx_skb = dev_alloc_skb(pkt_len);
+	if (!tx_skb) {
+		printk(KERN_ERR "dev_alloc_skb() failed during loopback test"
+			 " of %s\n", dev->name);
+		ret = 0;
+		goto out;
+	}
 	pkt_data = skb_put(tx_skb, pkt_len);
 	for (i = 0; i < pkt_len; i++)
 		pkt_data[i] = (u8)(i & 0xff);
@@ -3853,7 +3859,7 @@
 		       tx_skb->end-tx_skb->data,
 		       PCI_DMA_TODEVICE);
 	dev_kfree_skb_any(tx_skb);
-
+ out:
 	/* stop engines */
 	nv_stop_rx(dev);
 	nv_stop_tx(dev);
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index 95022c005..92590d8 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -6,11 +6,10 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/phy.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/fs_enet_pd.h>
 
-#include <asm/dma-mapping.h>
-
 #ifdef CONFIG_CPM1
 #include <asm/commproc.h>
 
diff --git a/drivers/net/gt64240eth.h b/drivers/net/gt64240eth.h
deleted file mode 100644
index 0d6f486..0000000
--- a/drivers/net/gt64240eth.h
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 Patton Electronics Company
- * Copyright (C) 2002 Momentum Computer
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *         	stevel@mvista.com or support@mvista.com
- *
- *  This program is free software; you can distribute 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 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.
- *
- * Ethernet driver definitions for the MIPS GT96100 Advanced
- * Communication Controller.
- *
- * Modified for the Marvellous GT64240 Retarded Communication Controller.
- */
-#ifndef _GT64240ETH_H
-#define _GT64240ETH_H
-
-#include <asm/gt64240.h>
-
-#define ETHERNET_PORTS_DIFFERENCE_OFFSETS	0x400
-
-/* Translate those weanie names from Galileo/VxWorks header files: */
-
-#define GT64240_MRR                    MAIN_ROUTING_REGISTER
-#define GT64240_CIU_ARBITER_CONFIG     COMM_UNIT_ARBITER_CONFIGURATION_REGISTER
-#define GT64240_CIU_ARBITER_CONTROL    COMM_UNIT_ARBITER_CONTROL
-#define GT64240_MAIN_LOW_CAUSE         LOW_INTERRUPT_CAUSE_REGISTER
-#define GT64240_MAIN_HIGH_CAUSE        HIGH_INTERRUPT_CAUSE_REGISTER
-#define GT64240_CPU_LOW_MASK           CPU_INTERRUPT_MASK_REGISTER_LOW
-#define GT64240_CPU_HIGH_MASK          CPU_INTERRUPT_MASK_REGISTER_HIGH
-#define GT64240_CPU_SELECT_CAUSE       CPU_SELECT_CAUSE_REGISTER
-
-#define GT64240_ETH_PHY_ADDR_REG       ETHERNET_PHY_ADDRESS_REGISTER
-#define GT64240_ETH_PORT_CONFIG        ETHERNET0_PORT_CONFIGURATION_REGISTER
-#define GT64240_ETH_PORT_CONFIG_EXT    ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER
-#define GT64240_ETH_PORT_COMMAND       ETHERNET0_PORT_COMMAND_REGISTER
-#define GT64240_ETH_PORT_STATUS        ETHERNET0_PORT_STATUS_REGISTER
-#define GT64240_ETH_IO_SIZE            ETHERNET_PORTS_DIFFERENCE_OFFSETS
-#define GT64240_ETH_SMI_REG            ETHERNET_SMI_REGISTER
-#define GT64240_ETH_MIB_COUNT_BASE     ETHERNET0_MIB_COUNTER_BASE
-#define GT64240_ETH_SDMA_CONFIG        ETHERNET0_SDMA_CONFIGURATION_REGISTER
-#define GT64240_ETH_SDMA_COMM          ETHERNET0_SDMA_COMMAND_REGISTER
-#define GT64240_ETH_INT_MASK           ETHERNET0_INTERRUPT_MASK_REGISTER
-#define GT64240_ETH_INT_CAUSE          ETHERNET0_INTERRUPT_CAUSE_REGISTER
-#define GT64240_ETH_CURR_TX_DESC_PTR0  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_TX_DESC_PTR1  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1
-#define GT64240_ETH_1ST_RX_DESC_PTR0   ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_RX_DESC_PTR0  ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_HASH_TBL_PTR       ETHERNET0_HASH_TABLE_POINTER_REGISTER
-
-/* Turn on NAPI by default */
-
-#define	GT64240_NAPI			1
-
-/* Some 64240 settings that SHOULD eventually be setup in PROM monitor: */
-/* (Board-specific to the DSL3224 Rev A board ONLY!)                    */
-#define D3224_MPP_CTRL0_SETTING		0x66669900
-#define D3224_MPP_CTRL1_SETTING		0x00000000
-#define D3224_MPP_CTRL2_SETTING		0x00887700
-#define D3224_MPP_CTRL3_SETTING		0x00000044
-#define D3224_GPP_IO_CTRL_SETTING	0x0000e800
-#define D3224_GPP_LEVEL_CTRL_SETTING	0xf001f703
-#define D3224_GPP_VALUE_SETTING		0x00000000
-
-/* Keep the ring sizes a power of two for efficiency. */
-//-#define TX_RING_SIZE 16
-#define TX_RING_SIZE	64	/* TESTING !!! */
-#define RX_RING_SIZE	32
-#define PKT_BUF_SZ	1536	/* Size of each temporary Rx buffer. */
-
-#define RX_HASH_TABLE_SIZE 16384
-#define HASH_HOP_NUMBER 12
-
-#define NUM_INTERFACES 3
-
-#define GT64240ETH_TX_TIMEOUT HZ/4
-
-#define MIPS_GT64240_BASE 0xf4000000
-#define GT64240_ETH0_BASE (MIPS_GT64240_BASE + GT64240_ETH_PORT_CONFIG)
-#define GT64240_ETH1_BASE (GT64240_ETH0_BASE + GT64240_ETH_IO_SIZE)
-#define GT64240_ETH2_BASE (GT64240_ETH1_BASE + GT64240_ETH_IO_SIZE)
-
-#if defined(CONFIG_MIPS_DSL3224)
-#define GT64240_ETHER0_IRQ 4
-#define GT64240_ETHER1_IRQ 4
-#else
-#define GT64240_ETHER0_IRQ -1
-#define GT64240_ETHER1_IRQ -1
-#endif
-
-#define REV_GT64240  0x1
-#define REV_GT64240A 0x10
-
-#define GT64240ETH_READ(gp, offset)					\
-	GT_READ((gp)->port_offset + (offset))
-
-#define GT64240ETH_WRITE(gp, offset, data)				\
-	GT_WRITE((gp)->port_offset + (offset), (data))
-
-#define GT64240ETH_SETBIT(gp, offset, bits)				\
-	GT64240ETH_WRITE((gp), (offset),				\
-	                 GT64240ETH_READ((gp), (offset)) | (bits))
-
-#define GT64240ETH_CLRBIT(gp, offset, bits)				\
-	GT64240ETH_WRITE((gp), (offset),				\
-	                 GT64240ETH_READ((gp), (offset)) & ~(bits))
-
-#define GT64240_READ(ofs)		GT_READ(ofs)
-#define GT64240_WRITE(ofs, data)	GT_WRITE((ofs), (data))
-
-/* Bit definitions of the SMI Reg */
-enum {
-	smirDataMask = 0xffff,
-	smirPhyAdMask = 0x1f << 16,
-	smirPhyAdBit = 16,
-	smirRegAdMask = 0x1f << 21,
-	smirRegAdBit = 21,
-	smirOpCode = 1 << 26,
-	smirReadValid = 1 << 27,
-	smirBusy = 1 << 28
-};
-
-/* Bit definitions of the Port Config Reg */
-enum pcr_bits {
-	pcrPM = 1 << 0,
-	pcrRBM = 1 << 1,
-	pcrPBF = 1 << 2,
-	pcrEN = 1 << 7,
-	pcrLPBKMask = 0x3 << 8,
-	pcrLPBKBit = 1 << 8,
-	pcrFC = 1 << 10,
-	pcrHS = 1 << 12,
-	pcrHM = 1 << 13,
-	pcrHDM = 1 << 14,
-	pcrHD = 1 << 15,
-	pcrISLMask = 0x7 << 28,
-	pcrISLBit = 28,
-	pcrACCS = 1 << 31
-};
-
-/* Bit definitions of the Port Config Extend Reg */
-enum pcxr_bits {
-	pcxrIGMP = 1,
-	pcxrSPAN = 2,
-	pcxrPAR = 4,
-	pcxrPRIOtxMask = 0x7 << 3,
-	pcxrPRIOtxBit = 3,
-	pcxrPRIOrxMask = 0x3 << 6,
-	pcxrPRIOrxBit = 6,
-	pcxrPRIOrxOverride = 1 << 8,
-	pcxrDPLXen = 1 << 9,
-	pcxrFCTLen = 1 << 10,
-	pcxrFLP = 1 << 11,
-	pcxrFCTL = 1 << 12,
-	pcxrMFLMask = 0x3 << 14,
-	pcxrMFLBit = 14,
-	pcxrMIBclrMode = 1 << 16,
-	pcxrSpeed = 1 << 18,
-	pcxrSpeeden = 1 << 19,
-	pcxrRMIIen = 1 << 20,
-	pcxrDSCPen = 1 << 21
-};
-
-/* Bit definitions of the Port Command Reg */
-enum pcmr_bits {
-	pcmrFJ = 1 << 15
-};
-
-
-/* Bit definitions of the Port Status Reg */
-enum psr_bits {
-	psrSpeed = 1,
-	psrDuplex = 2,
-	psrFctl = 4,
-	psrLink = 8,
-	psrPause = 1 << 4,
-	psrTxLow = 1 << 5,
-	psrTxHigh = 1 << 6,
-	psrTxInProg = 1 << 7
-};
-
-/* Bit definitions of the SDMA Config Reg */
-enum sdcr_bits {
-	sdcrRCMask = 0xf << 2,
-	sdcrRCBit = 2,
-	sdcrBLMR = 1 << 6,
-	sdcrBLMT = 1 << 7,
-	sdcrPOVR = 1 << 8,
-	sdcrRIFB = 1 << 9,
-	sdcrBSZMask = 0x3 << 12,
-	sdcrBSZBit = 12
-};
-
-/* Bit definitions of the SDMA Command Reg */
-enum sdcmr_bits {
-	sdcmrERD = 1 << 7,
-	sdcmrAR = 1 << 15,
-	sdcmrSTDH = 1 << 16,
-	sdcmrSTDL = 1 << 17,
-	sdcmrTXDH = 1 << 23,
-	sdcmrTXDL = 1 << 24,
-	sdcmrAT = 1 << 31
-};
-
-/* Bit definitions of the Interrupt Cause Reg */
-enum icr_bits {
-	icrRxBuffer = 1,
-	icrTxBufferHigh = 1 << 2,
-	icrTxBufferLow = 1 << 3,
-	icrTxEndHigh = 1 << 6,
-	icrTxEndLow = 1 << 7,
-	icrRxError = 1 << 8,
-	icrTxErrorHigh = 1 << 10,
-	icrTxErrorLow = 1 << 11,
-	icrRxOVR = 1 << 12,
-	icrTxUdr = 1 << 13,
-	icrRxBufferQ0 = 1 << 16,
-	icrRxBufferQ1 = 1 << 17,
-	icrRxBufferQ2 = 1 << 18,
-	icrRxBufferQ3 = 1 << 19,
-	icrRxErrorQ0 = 1 << 20,
-	icrRxErrorQ1 = 1 << 21,
-	icrRxErrorQ2 = 1 << 22,
-	icrRxErrorQ3 = 1 << 23,
-	icrMIIPhySTC = 1 << 28,
-	icrSMIdone = 1 << 29,
-	icrEtherIntSum = 1 << 31
-};
-
-
-/* The Rx and Tx descriptor lists. */
-#ifdef __LITTLE_ENDIAN
-typedef struct {
-	u32 cmdstat;
-	u16 reserved;		//-prk21aug01    u32 reserved:16;
-	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
-	u32 buff_ptr;
-	u32 next;
-} gt64240_td_t;
-
-typedef struct {
-	u32 cmdstat;
-	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
-	u16 buff_sz;		//-prk21aug01    u32 buff_sz:16;
-	u32 buff_ptr;
-	u32 next;
-} gt64240_rd_t;
-#elif defined(__BIG_ENDIAN)
-typedef struct {
-	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
-	u16 reserved;		//-prk21aug01    u32 reserved:16;
-	u32 cmdstat;
-	u32 next;
-	u32 buff_ptr;
-} gt64240_td_t;
-
-typedef struct {
-	u16 buff_sz;		//-prk21aug01    u32 buff_sz:16;
-	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
-	u32 cmdstat;
-	u32 next;
-	u32 buff_ptr;
-} gt64240_rd_t;
-#else
-#error Either __BIG_ENDIAN or __LITTLE_ENDIAN must be defined!
-#endif
-
-
-/* Values for the Tx command-status descriptor entry. */
-enum td_cmdstat {
-	txOwn = 1 << 31,
-	txAutoMode = 1 << 30,
-	txEI = 1 << 23,
-	txGenCRC = 1 << 22,
-	txPad = 1 << 18,
-	txFirst = 1 << 17,
-	txLast = 1 << 16,
-	txErrorSummary = 1 << 15,
-	txReTxCntMask = 0x0f << 10,
-	txReTxCntBit = 10,
-	txCollision = 1 << 9,
-	txReTxLimit = 1 << 8,
-	txUnderrun = 1 << 6,
-	txLateCollision = 1 << 5
-};
-
-
-/* Values for the Rx command-status descriptor entry. */
-enum rd_cmdstat {
-	rxOwn = 1 << 31,
-	rxAutoMode = 1 << 30,
-	rxEI = 1 << 23,
-	rxFirst = 1 << 17,
-	rxLast = 1 << 16,
-	rxErrorSummary = 1 << 15,
-	rxIGMP = 1 << 14,
-	rxHashExpired = 1 << 13,
-	rxMissedFrame = 1 << 12,
-	rxFrameType = 1 << 11,
-	rxShortFrame = 1 << 8,
-	rxMaxFrameLen = 1 << 7,
-	rxOverrun = 1 << 6,
-	rxCollision = 1 << 4,
-	rxCRCError = 1
-};
-
-/* Bit fields of a Hash Table Entry */
-enum hash_table_entry {
-	hteValid = 1,
-	hteSkip = 2,
-	hteRD = 4
-};
-
-// The MIB counters
-typedef struct {
-	u32 byteReceived;
-	u32 byteSent;
-	u32 framesReceived;
-	u32 framesSent;
-	u32 totalByteReceived;
-	u32 totalFramesReceived;
-	u32 broadcastFramesReceived;
-	u32 multicastFramesReceived;
-	u32 cRCError;
-	u32 oversizeFrames;
-	u32 fragments;
-	u32 jabber;
-	u32 collision;
-	u32 lateCollision;
-	u32 frames64;
-	u32 frames65_127;
-	u32 frames128_255;
-	u32 frames256_511;
-	u32 frames512_1023;
-	u32 frames1024_MaxSize;
-	u32 macRxError;
-	u32 droppedFrames;
-	u32 outMulticastFrames;
-	u32 outBroadcastFrames;
-	u32 undersizeFrames;
-} mib_counters_t;
-
-
-struct gt64240_private {
-	gt64240_rd_t *rx_ring;
-	gt64240_td_t *tx_ring;
-	// The Rx and Tx rings must be 16-byte aligned
-	dma_addr_t rx_ring_dma;
-	dma_addr_t tx_ring_dma;
-	char *hash_table;
-	// The Hash Table must be 8-byte aligned
-	dma_addr_t hash_table_dma;
-	int hash_mode;
-
-	// The Rx buffers must be 8-byte aligned
-	char *rx_buff;
-	dma_addr_t rx_buff_dma;
-	// Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
-	// of payload must be 8-byte aligned
-	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	int rx_next_out;	/* The next free ring entry to receive */
-	int tx_next_in;		/* The next free ring entry to send */
-	int tx_next_out;	/* The last ring entry the ISR processed */
-	int tx_count;		/* current # of pkts waiting to be sent in Tx ring */
-	int intr_work_done;	/* number of Rx and Tx pkts processed in the isr */
-	int tx_full;		/* Tx ring is full */
-
-	mib_counters_t mib;
-	struct net_device_stats stats;
-
-	int io_size;
-	int port_num;		// 0 or 1
-	u32 port_offset;
-
-	int phy_addr;		// PHY address
-	u32 last_psr;		// last value of the port status register
-
-	int options;		/* User-settable misc. driver options. */
-	int drv_flags;
-	spinlock_t lock;	/* Serialise access to device */
-	struct mii_if_info mii_if;
-
-	u32 msg_enable;
-};
-
-#endif /* _GT64240ETH_H */
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index e9e6d99..7c8ccc0 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -287,6 +287,7 @@
 config USB_IRDA
 	tristate "IrDA USB dongles"
 	depends on IRDA && USB
+	select FW_LOADER
 	---help---
 	  Say Y here if you want to build support for the USB IrDA FIR Dongle
 	  device driver.  To compile it as a module, choose M here: the module
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 2a0d538..383cef1 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -671,10 +671,8 @@
 			 * Jean II */
 			done = 1;
 			break;
-		case -ECONNABORTED:		/* -103 */
-		case -ECONNRESET:		/* -104 */
-		case -ETIMEDOUT:		/* -110 */
-		case -ENOENT:			/* -2 (urb unlinked by us)  */
+		case -ECONNRESET:
+		case -ENOENT:			/* urb unlinked by us */
 		default:			/* ??? - Play safe */
 			urb->status = 0;
 			netif_wake_queue(self->netdev);
@@ -712,10 +710,8 @@
 			 * Jean II */
 			done = 1;
 			break;
-		case -ECONNABORTED:		/* -103 */
-		case -ECONNRESET:		/* -104 */
-		case -ETIMEDOUT:		/* -110 */
-		case -ENOENT:			/* -2 (urb unlinked by us)  */
+		case -ECONNRESET:
+		case -ENOENT:			/* urb unlinked by us */
 		default:			/* ??? - Play safe */
 			if(skb != NULL) {
 				dev_kfree_skb_any(skb);
@@ -845,14 +841,14 @@
 			self->stats.rx_crc_errors++;	
 			/* Also precursor to a hot-unplug on UHCI. */
 			/* Fallthrough... */
-		case -ECONNRESET:		/* -104 */
+		case -ECONNRESET:
 			/* Random error, if I remember correctly */
 			/* uhci_cleanup_unlink() is going to kill the Rx
 			 * URB just after we return. No problem, at this
 			 * point the URB will be idle ;-) - Jean II */
-		case -ESHUTDOWN:		/* -108 */
+		case -ESHUTDOWN:
 			/* That's usually a hot-unplug. Submit will fail... */
-		case -ETIMEDOUT:		/* -110 */
+		case -ETIME:
 			/* Usually precursor to a hot-unplug on OHCI. */
 		default:
 			self->stats.rx_errors++;
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index cb62f2a..7185a4e 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -110,7 +110,7 @@
 	{ "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8, 
 	  nsc_ircc_probe_338, nsc_ircc_init_338 },
 	/* Contributed by Steffen Pingel - IBM X40 */
-	{ "PC8738x", { 0x164e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
+	{ "PC8738x", { 0x164e, 0x4e, 0x2e }, 0x20, 0xf4, 0xff,
 	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
 	/* Contributed by Jan Frey - IBM A30/A31 */
 	{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, 
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 2eff45b..22358ff 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -2354,6 +2354,26 @@
 #define PCIID_VENDOR_INTEL 0x8086
 #define PCIID_VENDOR_ALI 0x10b9
 static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = {
+	/*
+	 * Subsystems needing entries:
+	 * 0x10b9:0x1533 0x103c:0x0850 HP nx9010 family
+	 * 0x10b9:0x1533 0x0e11:0x005a Compaq nc4000 family
+	 * 0x8086:0x24cc 0x0e11:0x002a HP nx9000 family
+	 */
+	{
+		/* Guessed entry */
+		.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+		.device = 0x24cc,
+		.subvendor = 0x103c,
+		.subdevice = 0x08bc,
+		.sir_io = 0x02f8,
+		.fir_io = 0x0130,
+		.fir_irq = 0x05,
+		.fir_dma = 0x03,
+		.cfg_base = 0x004e,
+		.preconfigure = preconfigure_through_82801,
+		.name = "HP nx5000 family",
+	},
 	{
 		.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
 		.device = 0x24cc,
@@ -2366,7 +2386,7 @@
 		.fir_dma = 0x03,
 		.cfg_base = 0x004e,
 		.preconfigure = preconfigure_through_82801,
-		.name = "HP nc8000",
+		.name = "HP nc8000 family",
 	},
 	{
 		.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
@@ -2379,7 +2399,21 @@
 		.fir_dma = 0x03,
 		.cfg_base = 0x004e,
 		.preconfigure = preconfigure_through_82801,
-		.name = "HP nc6000",
+		.name = "HP nc6000 family",
+	},
+	{
+		.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+		.device = 0x24cc,
+		.subvendor = 0x0e11,
+		.subdevice = 0x0860,
+		/* I assume these are the same for x1000 as for the others */
+		.sir_io = 0x02e8,
+		.fir_io = 0x02f8,
+		.fir_irq = 0x07,
+		.fir_dma = 0x03,
+		.cfg_base = 0x002e,
+		.preconfigure = preconfigure_through_82801,
+		.name = "Compaq x1000 family",
 	},
 	{
 		/* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index d61b208..12103c9 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -149,8 +149,6 @@
 	FIFOCTL_DIR = 0x10,
 	FIFOCTL_CLR = 0x08,
 	FIFOCTL_EMPTY = 0x04,
-	FIFOCTL_RXERR = 0x02,
-	FIFOCTL_TXERR = 0x01,
 };
 
 enum StirDiagMask {
@@ -615,19 +613,6 @@
 
 		pr_debug("fifo status 0x%lx count %lu\n", status, count);
 
-		/* error when receive/transmit fifo gets confused */
-		if (status & FIFOCTL_RXERR) {
-			stir->stats.rx_fifo_errors++;
-			stir->stats.rx_errors++;
-			break;
-		}
-
-		if (status & FIFOCTL_TXERR) {
-			stir->stats.tx_fifo_errors++;
-			stir->stats.tx_errors++;
-			break;
-		}
-
 		/* is fifo receiving already, or empty */
 		if (!(status & FIFOCTL_DIR)
 		    || (status & FIFOCTL_EMPTY))
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index 79b85f3..d916e12 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -1223,8 +1223,13 @@
 
 	IRDA_DEBUG(2, "%s(): len=%x\n", __FUNCTION__, len);
 
+	if ((len - 4) < 2) {
+		self->stats.rx_dropped++;
+		return FALSE;
+	}
+
 	skb = dev_alloc_skb(len + 1);
-	if ((skb == NULL) || ((len - 4) < 2)) {
+	if (skb == NULL) {
 		self->stats.rx_dropped++;
 		return FALSE;
 	}
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index f429b19..4178b4b1 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -161,15 +161,13 @@
 	return(0);
 }
 
+static struct net_device_stats loopback_stats;
+
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
-	struct net_device_stats *stats = dev->priv;
+	struct net_device_stats *stats = &loopback_stats;
 	int i;
 
-	if (!stats) {
-		return NULL;
-	}
-
 	memset(stats, 0, sizeof(struct net_device_stats));
 
 	for_each_possible_cpu(i) {
@@ -185,19 +183,28 @@
 	return stats;
 }
 
-static u32 loopback_get_link(struct net_device *dev)
+static u32 always_on(struct net_device *dev)
 {
 	return 1;
 }
 
 static const struct ethtool_ops loopback_ethtool_ops = {
-	.get_link		= loopback_get_link,
+	.get_link		= always_on,
 	.get_tso		= ethtool_op_get_tso,
 	.set_tso		= ethtool_op_set_tso,
+	.get_tx_csum		= always_on,
+	.get_sg			= always_on,
+	.get_rx_csum		= always_on,
 };
 
+/*
+ * The loopback device is special. There is only one instance and
+ * it is statically allocated. Don't do this for other devices.
+ */
 struct net_device loopback_dev = {
 	.name	 		= "lo",
+	.get_stats		= &get_stats,
+	.priv			= &loopback_stats,
 	.mtu			= (16 * 1024) + 20 + 20 + 12,
 	.hard_start_xmit	= loopback_xmit,
 	.hard_header		= eth_header,
@@ -221,16 +228,6 @@
 /* Setup and register the loopback device. */
 int __init loopback_init(void)
 {
-	struct net_device_stats *stats;
-
-	/* Can survive without statistics */
-	stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
-	if (stats) {
-		memset(stats, 0, sizeof(struct net_device_stats));
-		loopback_dev.priv = stats;
-		loopback_dev.get_stats = &get_stats;
-	}
-
 	return register_netdev(&loopback_dev);
 };
 
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 2d1ecfd..ecd3da1 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -522,7 +522,7 @@
 
 static int genphy_config_init(struct phy_device *phydev)
 {
-	u32 val;
+	int val;
 	u32 features;
 
 	/* For now, I'll claim that the generic driver supports
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 5666ed9..0adee73 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -600,6 +600,7 @@
 		po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
 				   dev->hard_header_len);
 
+		po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
 		po->chan.private = sk;
 		po->chan.ops = &pppoe_chan_ops;
 
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index f5dbeb2..1bf23e4 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -2904,7 +2904,7 @@
 {
 	u64 val64 = 0x0;
 	nic_t *sp = dev->priv;
-	XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
 	//address transaction
 	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -2953,7 +2953,7 @@
 	u64 val64 = 0x0;
 	u64 rval64 = 0x0;
 	nic_t *sp = dev->priv;
-	XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
 	/* address transaction */
 	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -3276,7 +3276,7 @@
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(void *addr, u64 busy_bit)
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit)
 {
 	int ret = FAILURE, cnt = 0;
 	u64 val64;
@@ -4303,11 +4303,11 @@
 	sp->stats.tx_errors =
 		le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
 	sp->stats.rx_errors =
-		le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+		le64_to_cpu(mac_control->stats_info->rmac_drop_frms);
 	sp->stats.multicast =
 		le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
 	sp->stats.rx_length_errors =
-		le32_to_cpu(mac_control->stats_info->rmac_long_frms);
+		le64_to_cpu(mac_control->stats_info->rmac_long_frms);
 
 	return (&sp->stats);
 }
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 9142d91..705e9a8 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -58,6 +58,7 @@
 #define TX_WATCHDOG		(5 * HZ)
 #define NAPI_WEIGHT		64
 #define BLINK_MS		250
+#define LINK_HZ			(HZ/2)
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
 MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -605,7 +606,12 @@
 	if (hw->chip_id == CHIP_ID_GENESIS) {
 		switch (mode) {
 		case LED_MODE_OFF:
-			xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+			if (hw->phy_type == SK_PHY_BCOM)
+				xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+			else {
+				skge_write32(hw, SK_REG(port, TX_LED_VAL), 0);
+				skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF);
+			}
 			skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
 			skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
 			skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
@@ -625,8 +631,14 @@
 			skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
 			skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
 
-			xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
-			break;
+			if (hw->phy_type == SK_PHY_BCOM)
+				xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+			else {
+				skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON);
+				skge_write32(hw, SK_REG(port, TX_LED_VAL), 100);
+				skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
+			}
+
 		}
 	} else {
 		switch (mode) {
@@ -879,6 +891,9 @@
 	xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
 	*val = xm_read16(hw, port, XM_PHY_DATA);
 
+	if (hw->phy_type == SK_PHY_XMAC)
+		goto ready;
+
 	for (i = 0; i < PHY_RETRIES; i++) {
 		if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
 			goto ready;
@@ -965,7 +980,8 @@
 	xm_write16(hw, port, XM_RX_CMD, 0);	/* reset RX CMD Reg */
 
 	/* disable Broadcom PHY IRQ */
-	xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+	if (hw->phy_type == SK_PHY_BCOM)
+		xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
 
 	xm_outhash(hw, port, XM_HSM, zero);
 }
@@ -1000,60 +1016,64 @@
 
 		if (netif_carrier_ok(dev))
 			skge_link_down(skge);
-	} else {
-		if (skge->autoneg == AUTONEG_ENABLE &&
-		    (status & PHY_ST_AN_OVER)) {
-			u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP);
-			u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+		return;
+	}
 
-			if (lpa & PHY_B_AN_RF) {
-				printk(KERN_NOTICE PFX "%s: remote fault\n",
-				       dev->name);
-				return;
-			}
+	if (skge->autoneg == AUTONEG_ENABLE) {
+		u16 lpa, aux;
 
-			/* Check Duplex mismatch */
-			switch (aux & PHY_B_AS_AN_RES_MSK) {
-			case PHY_B_RES_1000FD:
-				skge->duplex = DUPLEX_FULL;
-				break;
-			case PHY_B_RES_1000HD:
-				skge->duplex = DUPLEX_HALF;
-				break;
-			default:
-				printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
-				       dev->name);
-				return;
-			}
+		if (!(status & PHY_ST_AN_OVER))
+			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;
-				break;
-			case PHY_B_AS_PRR:
-				skge->flow_control = FLOW_MODE_REM_SEND;
-				break;
-			case PHY_B_AS_PRT:
-				skge->flow_control = FLOW_MODE_LOC_SEND;
-				break;
-			default:
-				skge->flow_control = FLOW_MODE_NONE;
-			}
-
-			skge->speed = SPEED_1000;
+		lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+		if (lpa & PHY_B_AN_RF) {
+			printk(KERN_NOTICE PFX "%s: remote fault\n",
+			       dev->name);
+			return;
 		}
 
-		if (!netif_carrier_ok(dev))
-			genesis_link_up(skge);
+		aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+
+		/* Check Duplex mismatch */
+		switch (aux & PHY_B_AS_AN_RES_MSK) {
+		case PHY_B_RES_1000FD:
+			skge->duplex = DUPLEX_FULL;
+			break;
+		case PHY_B_RES_1000HD:
+			skge->duplex = DUPLEX_HALF;
+			break;
+		default:
+			printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+			       dev->name);
+			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;
+			break;
+		case PHY_B_AS_PRR:
+			skge->flow_control = FLOW_MODE_REM_SEND;
+			break;
+		case PHY_B_AS_PRT:
+			skge->flow_control = FLOW_MODE_LOC_SEND;
+			break;
+		default:
+			skge->flow_control = FLOW_MODE_NONE;
+		}
+		skge->speed = SPEED_1000;
 	}
+
+	if (!netif_carrier_ok(dev))
+		genesis_link_up(skge);
 }
 
 /* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional
  * Phy on for 100 or 10Mbit operation
  */
-static void bcom_phy_init(struct skge_port *skge, int jumbo)
+static void bcom_phy_init(struct skge_port *skge)
 {
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
@@ -1144,7 +1164,7 @@
 		     phy_pause_map[skge->flow_control] | PHY_AN_CSMA);
 
 	/* Handle Jumbo frames */
-	if (jumbo) {
+	if (hw->dev[port]->mtu > ETH_DATA_LEN) {
 		xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
 			     PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK);
 
@@ -1157,8 +1177,154 @@
 
 	/* Use link status change interrupt */
 	xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+}
 
-	bcom_check_link(hw, port);
+static void xm_phy_init(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u16 ctrl = 0;
+
+	if (skge->autoneg == AUTONEG_ENABLE) {
+		if (skge->advertising & ADVERTISED_1000baseT_Half)
+			ctrl |= PHY_X_AN_HD;
+		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;
+		}
+
+		xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl);
+
+		/* Restart Auto-negotiation */
+		ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+	} else {
+		/* Set DuplexMode in Config register */
+		if (skge->duplex == DUPLEX_FULL)
+			ctrl |= PHY_CT_DUP_MD;
+		/*
+		 * Do NOT enable Auto-negotiation here. This would hold
+		 * the link down because no IDLEs are transmitted
+		 */
+	}
+
+	xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
+
+	/* Poll PHY for status changes */
+	schedule_delayed_work(&skge->link_thread, LINK_HZ);
+}
+
+static void xm_check_link(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u16 status;
+
+	/* read twice because of latch */
+	(void) xm_phy_read(hw, port, PHY_XMAC_STAT);
+	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);
+		return;
+	}
+
+	if (skge->autoneg == AUTONEG_ENABLE) {
+		u16 lpa, res;
+
+		if (!(status & PHY_ST_AN_OVER))
+			return;
+
+		lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+		if (lpa & PHY_B_AN_RF) {
+			printk(KERN_NOTICE PFX "%s: remote fault\n",
+			       dev->name);
+			return;
+		}
+
+		res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI);
+
+		/* Check Duplex mismatch */
+		switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) {
+		case PHY_X_RS_FD:
+			skge->duplex = DUPLEX_FULL;
+			break;
+		case PHY_X_RS_HD:
+			skge->duplex = DUPLEX_HALF;
+			break;
+		default:
+			printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+			       dev->name);
+			return;
+		}
+
+		/* 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;
+		else
+			skge->flow_control = FLOW_MODE_NONE;
+
+
+		skge->speed = SPEED_1000;
+	}
+
+	if (!netif_carrier_ok(dev))
+		genesis_link_up(skge);
+}
+
+/* Poll to check for link coming up.
+ * Since internal PHY is wired to a level triggered pin, can't
+ * get an interrupt when carrier is detected.
+ */
+static void xm_link_timer(void *arg)
+{
+	struct net_device *dev = arg;
+	struct skge_port *skge = netdev_priv(arg);
+ 	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	if (!netif_running(dev))
+		return;
+
+	if (netif_carrier_ok(dev)) {
+		xm_read16(hw, port, XM_ISRC);
+		if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS))
+			goto nochange;
+	} else {
+		if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+			goto nochange;
+		xm_read16(hw, port, XM_ISRC);
+		if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
+			goto nochange;
+	}
+
+	mutex_lock(&hw->phy_mutex);
+	xm_check_link(dev);
+	mutex_unlock(&hw->phy_mutex);
+
+nochange:
+	schedule_delayed_work(&skge->link_thread, LINK_HZ);
 }
 
 static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -1189,20 +1355,29 @@
 	 * namely for the 1000baseTX cards that use the XMAC's
 	 * GMII mode.
 	 */
-	/* Take external Phy out of reset */
-	r = skge_read32(hw, B2_GP_IO);
-	if (port == 0)
-		r |= GP_DIR_0|GP_IO_0;
-	else
-		r |= GP_DIR_2|GP_IO_2;
+	if (hw->phy_type != SK_PHY_XMAC) {
+		/* Take external Phy out of reset */
+		r = skge_read32(hw, B2_GP_IO);
+		if (port == 0)
+			r |= GP_DIR_0|GP_IO_0;
+		else
+			r |= GP_DIR_2|GP_IO_2;
 
-	skge_write32(hw, B2_GP_IO, r);
+		skge_write32(hw, B2_GP_IO, r);
+
+		/* Enable GMII interface */
+		xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+	}
 
 
-	/* Enable GMII interface */
-	xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
-
-	bcom_phy_init(skge, jumbo);
+	switch(hw->phy_type) {
+	case SK_PHY_XMAC:
+		xm_phy_init(skge);
+		break;
+	case SK_PHY_BCOM:
+		bcom_phy_init(skge);
+		bcom_check_link(hw, port);
+	}
 
 	/* Set Station Address */
 	xm_outaddr(hw, port, XM_SA, dev->dev_addr);
@@ -1335,16 +1510,18 @@
 	skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
 
 	/* For external PHYs there must be special handling */
-	reg = skge_read32(hw, B2_GP_IO);
-	if (port == 0) {
-		reg |= GP_DIR_0;
-		reg &= ~GP_IO_0;
-	} else {
-		reg |= GP_DIR_2;
-		reg &= ~GP_IO_2;
+	if (hw->phy_type != SK_PHY_XMAC) {
+		reg = skge_read32(hw, B2_GP_IO);
+		if (port == 0) {
+			reg |= GP_DIR_0;
+			reg &= ~GP_IO_0;
+		} else {
+			reg |= GP_DIR_2;
+			reg &= ~GP_IO_2;
+		}
+		skge_write32(hw, B2_GP_IO, reg);
+		skge_read32(hw, B2_GP_IO);
 	}
-	skge_write32(hw, B2_GP_IO, reg);
-	skge_read32(hw, B2_GP_IO);
 
 	xm_write16(hw, port, XM_MMU_CMD,
 			xm_read16(hw, port, XM_MMU_CMD)
@@ -1406,7 +1583,7 @@
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
 	u16 cmd;
-	u32 mode, msk;
+	u32 mode;
 
 	cmd = xm_read16(hw, port, XM_MMU_CMD);
 
@@ -1454,27 +1631,24 @@
 	}
 
 	xm_write32(hw, port, XM_MODE, mode);
-
-	msk = XM_DEF_MSK;
-	/* disable GP0 interrupt bit for external Phy */
-	msk |= XM_IS_INP_ASS;
-
-	xm_write16(hw, port, XM_IMSK, msk);
+	xm_write16(hw, port, XM_IMSK, XM_DEF_MSK);
 	xm_read16(hw, port, XM_ISRC);
 
 	/* get MMU Command Reg. */
 	cmd = xm_read16(hw, port, XM_MMU_CMD);
-	if (skge->duplex == DUPLEX_FULL)
+	if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
 		cmd |= XM_MMU_GMII_FD;
 
 	/*
 	 * Workaround BCOM Errata (#10523) for all BCom Phys
 	 * Enable Power Management after link up
 	 */
-	xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
-		     xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
-		     & ~PHY_B_AC_DIS_PM);
-	xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+	if (hw->phy_type == SK_PHY_BCOM) {
+		xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+			     xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+			     & ~PHY_B_AC_DIS_PM);
+		xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+	}
 
 	/* enable Rx/Tx */
 	xm_write16(hw, port, XM_MMU_CMD,
@@ -2240,6 +2414,8 @@
 		printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
 	netif_stop_queue(dev);
+	if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
+		cancel_rearming_delayed_work(&skge->link_thread);
 
 	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
 	if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2862,7 +3038,7 @@
 		if (netif_running(dev)) {
 			if (hw->chip_id != CHIP_ID_GENESIS)
 				yukon_phy_intr(skge);
-			else
+			else if (hw->phy_type == SK_PHY_BCOM)
 				bcom_phy_intr(skge);
 		}
 	}
@@ -3014,7 +3190,7 @@
 {
 	u32 reg;
 	u16 ctst, pci_status;
-	u8 t8, mac_cfg, pmd_type, phy_type;
+	u8 t8, mac_cfg, pmd_type;
 	int i;
 
 	ctst = skge_read16(hw, B0_CTST);
@@ -3038,19 +3214,22 @@
 		     ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
 
 	hw->chip_id = skge_read8(hw, B2_CHIP_ID);
-	phy_type = skge_read8(hw, B2_E_1) & 0xf;
+	hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
 	pmd_type = skge_read8(hw, B2_PMD_TYP);
 	hw->copper = (pmd_type == 'T' || pmd_type == '1');
 
 	switch (hw->chip_id) {
 	case CHIP_ID_GENESIS:
-		switch (phy_type) {
+		switch (hw->phy_type) {
+		case SK_PHY_XMAC:
+			hw->phy_addr = PHY_ADDR_XMAC;
+			break;
 		case SK_PHY_BCOM:
 			hw->phy_addr = PHY_ADDR_BCOM;
 			break;
 		default:
 			printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
-			       pci_name(hw->pdev), phy_type);
+			       pci_name(hw->pdev), hw->phy_type);
 			return -EOPNOTSUPP;
 		}
 		break;
@@ -3058,7 +3237,7 @@
 	case CHIP_ID_YUKON:
 	case CHIP_ID_YUKON_LITE:
 	case CHIP_ID_YUKON_LP:
-		if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+		if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
 			hw->copper = 1;
 
 		hw->phy_addr = PHY_ADDR_MARV;
@@ -3089,10 +3268,13 @@
 	else
 		hw->ram_size = t8 * 4096;
 
-	hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
+	hw->intr_mask = IS_HW_ERR | IS_PORT_1;
 	if (hw->ports > 1)
 		hw->intr_mask |= IS_PORT_2;
 
+	if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
+		hw->intr_mask |= IS_EXT_REG;
+
 	if (hw->chip_id == CHIP_ID_GENESIS)
 		genesis_init(hw);
 	else {
@@ -3226,6 +3408,9 @@
 
 	skge->port = port;
 
+	/* Only used for Genesis XMAC */
+	INIT_WORK(&skge->link_thread, xm_link_timer, dev);
+
 	if (hw->chip_id != CHIP_ID_GENESIS) {
 		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 		skge->rx_csum = 1;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 79e0927..d0b47d4 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -934,7 +934,7 @@
 	PHY_XMAC_AUNE_ADV	= 0x04,/* 16 bit r/w	Auto-Neg. Advertisement */
 	PHY_XMAC_AUNE_LP	= 0x05,/* 16 bit r/o	Link Partner Abi Reg */
 	PHY_XMAC_AUNE_EXP	= 0x06,/* 16 bit r/o	Auto-Neg. Expansion Reg */
-	PHY_XMAC_NEPG	= 0x07,/* 16 bit r/w	Next Page Register */
+	PHY_XMAC_NEPG		= 0x07,/* 16 bit r/w	Next Page Register */
 	PHY_XMAC_NEPG_LP	= 0x08,/* 16 bit r/o	Next Page Link Partner */
 
 	PHY_XMAC_EXT_STAT	= 0x0f,/* 16 bit r/o	Ext Status Register */
@@ -1097,13 +1097,36 @@
 
 /* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
 enum {
-	PHY_X_P_NO_PAUSE	= 0<<7,/* Bit  8..7:	no Pause Mode */
+	PHY_X_P_NO_PAUSE= 0<<7,/* Bit  8..7:	no Pause Mode */
 	PHY_X_P_SYM_MD	= 1<<7, /* Bit  8..7:	symmetric Pause Mode */
 	PHY_X_P_ASYM_MD	= 2<<7,/* Bit  8..7:	asymmetric Pause Mode */
 	PHY_X_P_BOTH_MD	= 3<<7,/* Bit  8..7:	both Pause Mode */
 };
 
 
+/*****  PHY_XMAC_EXT_STAT	16 bit r/w	Extended Status Register *****/
+enum {
+	PHY_X_EX_FD	= 1<<15, /* Bit 15:	Device Supports Full Duplex */
+	PHY_X_EX_HD	= 1<<14, /* Bit 14:	Device Supports Half Duplex */
+};
+
+/*****  PHY_XMAC_RES_ABI	16 bit r/o	PHY Resolved Ability *****/
+enum {
+	PHY_X_RS_PAUSE	= 3<<7,	/* Bit  8..7:	selected Pause Mode */
+	PHY_X_RS_HD	= 1<<6,	/* Bit  6:	Half Duplex Mode selected */
+	PHY_X_RS_FD	= 1<<5,	/* Bit  5:	Full Duplex Mode selected */
+	PHY_X_RS_ABLMIS = 1<<4,	/* Bit  4:	duplex or pause cap mismatch */
+	PHY_X_RS_PAUMIS = 1<<3,	/* Bit  3:	pause capability mismatch */
+};
+
+/* Remote Fault Bits (PHY_X_AN_RFB) encoding */
+enum {
+	X_RFB_OK	= 0<<12,/* Bit 13..12	No errors, Link OK */
+	X_RFB_LF	= 1<<12,/* Bit 13..12	Link Failure */
+	X_RFB_OFF	= 2<<12,/* Bit 13..12	Offline */
+	X_RFB_AN_ERR	= 3<<12,/* Bit 13..12	Auto-Negotiation Error */
+};
+
 /* Broadcom-Specific */
 /*****  PHY_BCOM_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
 enum {
@@ -2158,8 +2181,8 @@
 	XM_IS_LNK_AE	= 1<<14, /* Bit 14:	Link Asynchronous Event */
 	XM_IS_TX_ABORT	= 1<<13, /* Bit 13:	Transmit Abort, late Col. etc */
 	XM_IS_FRC_INT	= 1<<12, /* Bit 12:	Force INT bit set in GP */
-	XM_IS_INP_ASS	= 1<<11,	/* Bit 11:	Input Asserted, GP bit 0 set */
-	XM_IS_LIPA_RC	= 1<<10,	/* Bit 10:	Link Partner requests config */
+	XM_IS_INP_ASS	= 1<<11, /* Bit 11:	Input Asserted, GP bit 0 set */
+	XM_IS_LIPA_RC	= 1<<10, /* Bit 10:	Link Partner requests config */
 	XM_IS_RX_PAGE	= 1<<9,	/* Bit  9:	Page Received */
 	XM_IS_TX_PAGE	= 1<<8,	/* Bit  8:	Next Page Loaded for Transmit */
 	XM_IS_AND	= 1<<7,	/* Bit  7:	Auto-Negotiation Done */
@@ -2172,9 +2195,7 @@
 	XM_IS_RX_COMP	= 1<<0,	/* Bit  0:	Frame Rx Complete */
 };
 
-#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | \
-			   XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | \
-			   XM_IS_RXF_OV | XM_IS_TXF_UR))
+#define XM_DEF_MSK	(~(XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_RXF_OV | XM_IS_TXF_UR))
 
 
 /*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
@@ -2396,6 +2417,7 @@
 	u8		     chip_rev;
 	u8		     copper;
 	u8		     ports;
+	u8		     phy_type;
 
 	u32	     	     ram_size;
 	u32	     	     ram_offset;
@@ -2422,6 +2444,7 @@
 
 	struct net_device_stats net_stats;
 
+	struct work_struct   link_thread;
 	u8		     rx_csum;
 	u8		     blink_on;
 	u8		     flow_control;
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 7aa7fba..fedd1a3 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -195,6 +195,7 @@
 #define	SMC_IRQ_FLAGS (( \
 		   machine_is_omap_h2() \
 		|| machine_is_omap_h3() \
+		|| machine_is_omap_h4() \
 		|| (machine_is_omap_innovator() && !cpu_is_omap1510()) \
 	) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING)
 
@@ -379,6 +380,24 @@
 
 #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
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index aaf45b9..c25ba27 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.65"
-#define DRV_MODULE_RELDATE	"August 07, 2006"
+#define DRV_MODULE_VERSION	"3.66"
+#define DRV_MODULE_RELDATE	"September 23, 2006"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -173,6 +173,7 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)},
@@ -187,6 +188,7 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
@@ -197,6 +199,8 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -424,6 +428,16 @@
 		readl(mbox);
 }
 
+static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
+{
+	return (readl(tp->regs + off + GRCMBOX_BASE));
+}
+
+static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
+{
+	writel(val, tp->regs + off + GRCMBOX_BASE);
+}
+
 #define tw32_mailbox(reg, val)	tp->write32_mbox(tp, reg, val)
 #define tw32_mailbox_f(reg, val)	tw32_mailbox_flush(tp, (reg), (val))
 #define tw32_rx_mbox(reg, val)	tp->write32_rx_mbox(tp, reg, val)
@@ -439,6 +453,10 @@
 {
 	unsigned long flags;
 
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+	    (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
+		return;
+
 	spin_lock_irqsave(&tp->indirect_lock, flags);
 	if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
 		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
@@ -460,6 +478,12 @@
 {
 	unsigned long flags;
 
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+	    (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
+		*val = 0;
+		return;
+	}
+
 	spin_lock_irqsave(&tp->indirect_lock, flags);
 	if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
 		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
@@ -489,6 +513,9 @@
 	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
 	    (tp->hw_status->status & SD_STATUS_UPDATED))
 		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+	else
+		tw32(HOSTCC_MODE, tp->coalesce_mode |
+		     (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
 }
 
 static void tg3_enable_ints(struct tg3 *tp)
@@ -654,6 +681,10 @@
 	unsigned int loops;
 	int ret;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+	    (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+		return 0;
+
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
@@ -1004,6 +1035,24 @@
 				 phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
 	}
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		u32 phy_reg;
+
+		/* adjust output voltage */
+		tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
+
+		if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) {
+			u32 phy_reg2;
+
+			tg3_writephy(tp, MII_TG3_EPHY_TEST,
+				     phy_reg | MII_TG3_EPHY_SHADOW_EN);
+			/* Enable auto-MDIX */
+			if (!tg3_readphy(tp, 0x10, &phy_reg2))
+				tg3_writephy(tp, 0x10, phy_reg2 | 0x4000);
+			tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg);
+		}
+	}
+
 	tg3_phy_set_wirespeed(tp);
 	return 0;
 }
@@ -1117,6 +1166,15 @@
 
 static void tg3_power_down_phy(struct tg3 *tp)
 {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+		return;
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
+		tg3_writephy(tp, MII_TG3_EXT_CTRL,
+			     MII_TG3_EXT_CTRL_FORCE_LED_OFF);
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+	}
+
 	/* The PHY should not be powered down on some chips because
 	 * of bugs.
 	 */
@@ -1199,7 +1257,12 @@
 		tg3_setup_phy(tp, 0);
 	}
 
-	if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		u32 val;
+
+		val = tr32(GRC_VCPU_EXT_CTRL);
+		tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL);
+	} else if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
 		int i;
 		u32 val;
 
@@ -1223,7 +1286,10 @@
 			tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
 			udelay(40);
 
-			mac_mode = MAC_MODE_PORT_MODE_MII;
+			if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+				mac_mode = MAC_MODE_PORT_MODE_GMII;
+			else
+				mac_mode = MAC_MODE_PORT_MODE_MII;
 
 			if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
 			    !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
@@ -1301,15 +1367,8 @@
 	}
 
 	if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
-	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
-		/* Turn off the PHY */
-		if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
-			tg3_writephy(tp, MII_TG3_EXT_CTRL,
-				     MII_TG3_EXT_CTRL_FORCE_LED_OFF);
-			tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
-			tg3_power_down_phy(tp);
-		}
-	}
+	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+		tg3_power_down_phy(tp);
 
 	tg3_frob_aux_power(tp);
 
@@ -1467,6 +1526,13 @@
 		break;
 
 	default:
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+			*speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+				 SPEED_10;
+			*duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+				  DUPLEX_HALF;
+			break;
+		}
 		*speed = SPEED_INVALID;
 		*duplex = DUPLEX_INVALID;
 		break;
@@ -1749,7 +1815,7 @@
 
 	if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT)
 		tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
-	else
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
 		tg3_writephy(tp, MII_TG3_IMASK, ~0);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
@@ -2406,24 +2472,27 @@
 	expected_sg_dig_ctrl |= (1 << 12);
 
 	if (sg_dig_ctrl != expected_sg_dig_ctrl) {
+		if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) &&
+		    tp->serdes_counter &&
+		    ((mac_status & (MAC_STATUS_PCS_SYNCED |
+				    MAC_STATUS_RCVD_CFG)) ==
+		     MAC_STATUS_PCS_SYNCED)) {
+			tp->serdes_counter--;
+			current_link_up = 1;
+			goto out;
+		}
+restart_autoneg:
 		if (workaround)
 			tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000);
 		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
 		udelay(5);
 		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
 
-		tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
+		tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
+		tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
 	} else if (mac_status & (MAC_STATUS_PCS_SYNCED |
 				 MAC_STATUS_SIGNAL_DET)) {
-		int i;
-
-		/* Giver time to negotiate (~200ms) */
-		for (i = 0; i < 40000; i++) {
-			sg_dig_status = tr32(SG_DIG_STATUS);
-			if (sg_dig_status & (0x3))
-				break;
-			udelay(5);
-		}
+		sg_dig_status = tr32(SG_DIG_STATUS);
 		mac_status = tr32(MAC_STATUS);
 
 		if ((sg_dig_status & (1 << 1)) &&
@@ -2439,10 +2508,11 @@
 
 			tg3_setup_flow_control(tp, local_adv, remote_adv);
 			current_link_up = 1;
-			tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+			tp->serdes_counter = 0;
+			tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
 		} else if (!(sg_dig_status & (1 << 1))) {
-			if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED)
-				tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+			if (tp->serdes_counter)
+				tp->serdes_counter--;
 			else {
 				if (workaround) {
 					u32 val = serdes_cfg;
@@ -2466,9 +2536,17 @@
 				    !(mac_status & MAC_STATUS_RCVD_CFG)) {
 					tg3_setup_flow_control(tp, 0, 0);
 					current_link_up = 1;
-				}
+					tp->tg3_flags2 |=
+						TG3_FLG2_PARALLEL_DETECT;
+					tp->serdes_counter =
+						SERDES_PARALLEL_DET_TIMEOUT;
+				} else
+					goto restart_autoneg;
 			}
 		}
+	} else {
+		tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
+		tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
 	}
 
 out:
@@ -2599,14 +2677,16 @@
 				    MAC_STATUS_CFG_CHANGED));
 		udelay(5);
 		if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
-					 MAC_STATUS_CFG_CHANGED)) == 0)
+					 MAC_STATUS_CFG_CHANGED |
+					 MAC_STATUS_LNKSTATE_CHANGED)) == 0)
 			break;
 	}
 
 	mac_status = tr32(MAC_STATUS);
 	if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
 		current_link_up = 0;
-		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+		if (tp->link_config.autoneg == AUTONEG_ENABLE &&
+		    tp->serdes_counter == 0) {
 			tw32_f(MAC_MODE, (tp->mac_mode |
 					  MAC_MODE_SEND_CONFIGS));
 			udelay(1);
@@ -2711,7 +2791,7 @@
 			tg3_writephy(tp, MII_BMCR, bmcr);
 
 			tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
-			tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
+			tp->serdes_counter = SERDES_AN_TIMEOUT_5714S;
 			tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
 
 			return err;
@@ -2816,9 +2896,9 @@
 
 static void tg3_serdes_parallel_detect(struct tg3 *tp)
 {
-	if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) {
+	if (tp->serdes_counter) {
 		/* Give autoneg time to complete. */
-		tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+		tp->serdes_counter--;
 		return;
 	}
 	if (!netif_carrier_ok(tp->dev) &&
@@ -3535,8 +3615,7 @@
 
 	if ((sblk->status & SD_STATUS_UPDATED) ||
 	    !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
-		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-			     0x00000001);
+		tg3_disable_ints(tp);
 		return IRQ_RETVAL(1);
 	}
 	return IRQ_RETVAL(0);
@@ -4644,6 +4723,44 @@
 	}
 }
 
+static int tg3_poll_fw(struct tg3 *tp)
+{
+	int i;
+	u32 val;
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		for (i = 0; i < 400; i++) {
+			if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
+				return 0;
+			udelay(10);
+		}
+		return -ENODEV;
+	}
+
+	/* Wait for firmware initialization to complete. */
+	for (i = 0; i < 100000; i++) {
+		tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+		if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+			break;
+		udelay(10);
+	}
+
+	/* Chip might not be fitted with firmware.  Some Sun onboard
+	 * parts are configured like that.  So don't signal the timeout
+	 * of the above loop as an error, but do report the lack of
+	 * running firmware once.
+	 */
+	if (i >= 100000 &&
+	    !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
+		tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
+
+		printk(KERN_INFO PFX "%s: No firmware running.\n",
+		       tp->dev->name);
+	}
+
+	return 0;
+}
+
 static void tg3_stop_fw(struct tg3 *);
 
 /* tp->lock is held. */
@@ -4651,7 +4768,7 @@
 {
 	u32 val;
 	void (*write_op)(struct tg3 *, u32, u32);
-	int i;
+	int err;
 
 	tg3_nvram_lock(tp);
 
@@ -4688,6 +4805,12 @@
 		}
 	}
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET);
+		tw32(GRC_VCPU_EXT_CTRL,
+		     tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU);
+	}
+
 	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
 		val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
 	tw32(GRC_MISC_CFG, val);
@@ -4811,26 +4934,9 @@
 		tw32_f(MAC_MODE, 0);
 	udelay(40);
 
-	/* Wait for firmware initialization to complete. */
-	for (i = 0; i < 100000; i++) {
-		tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
-		if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-			break;
-		udelay(10);
-	}
-
-	/* Chip might not be fitted with firmare.  Some Sun onboard
-	 * parts are configured like that.  So don't signal the timeout
-	 * of the above loop as an error, but do report the lack of
-	 * running firmware once.
-	 */
-	if (i >= 100000 &&
-	    !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
-		tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
-
-		printk(KERN_INFO PFX "%s: No firmware running.\n",
-		       tp->dev->name);
-	}
+	err = tg3_poll_fw(tp);
+	if (err)
+		return err;
 
 	if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
 	    tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
@@ -5036,6 +5142,12 @@
 	BUG_ON(offset == TX_CPU_BASE &&
 	    (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		u32 val = tr32(GRC_VCPU_EXT_CTRL);
+
+		tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
+		return 0;
+	}
 	if (offset == RX_CPU_BASE) {
 		for (i = 0; i < 10000; i++) {
 			tw32(offset + CPU_STATE, 0xffffffff);
@@ -6040,6 +6152,13 @@
 		val = 1;
 	else if (val > tp->rx_std_max_post)
 		val = tp->rx_std_max_post;
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1)
+			tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2);
+
+		if (val > (TG3_RX_INTERNAL_RING_SZ_5906 / 2))
+			val = TG3_RX_INTERNAL_RING_SZ_5906 / 2;
+	}
 
 	tw32(RCVBDI_STD_THRESH, val);
 
@@ -6460,7 +6579,8 @@
 	if (err)
 		return err;
 
-	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
 		u32 tmp;
 
 		/* Clear CRC stats. */
@@ -6660,12 +6780,14 @@
 				need_setup = 1;
 			}
 			if (need_setup) {
-				tw32_f(MAC_MODE,
-				     (tp->mac_mode &
-				      ~MAC_MODE_PORT_MODE_MASK));
-				udelay(40);
-				tw32_f(MAC_MODE, tp->mac_mode);
-				udelay(40);
+				if (!tp->serdes_counter) {
+					tw32_f(MAC_MODE,
+					     (tp->mac_mode &
+					      ~MAC_MODE_PORT_MODE_MASK));
+					udelay(40);
+					tw32_f(MAC_MODE, tp->mac_mode);
+					udelay(40);
+				}
 				tg3_setup_phy(tp, 0);
 			}
 		} else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
@@ -6674,13 +6796,29 @@
 		tp->timer_counter = tp->timer_multiplier;
 	}
 
-	/* Heartbeat is only sent once every 2 seconds.  */
+	/* Heartbeat is only sent once every 2 seconds.
+	 *
+	 * The heartbeat is to tell the ASF firmware that the host
+	 * driver is still alive.  In the event that the OS crashes,
+	 * ASF needs to reset the hardware to free up the FIFO space
+	 * that may be filled with rx packets destined for the host.
+	 * If the FIFO is full, ASF will no longer function properly.
+	 *
+	 * Unintended resets have been reported on real time kernels
+	 * where the timer doesn't run on time.  Netpoll will also have
+	 * same problem.
+	 *
+	 * The new FWCMD_NICDRV_ALIVE3 command tells the ASF firmware
+	 * to check the ring condition when the heartbeat is expiring
+	 * before doing the reset.  This will prevent most unintended
+	 * resets.
+	 */
 	if (!--tp->asf_counter) {
 		if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
 			u32 val;
 
 			tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
-				      FWCMD_NICDRV_ALIVE2);
+				      FWCMD_NICDRV_ALIVE3);
 			tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
 			/* 5 seconds timeout */
 			tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
@@ -6721,8 +6859,7 @@
 static int tg3_test_interrupt(struct tg3 *tp)
 {
 	struct net_device *dev = tp->dev;
-	int err, i;
-	u32 int_mbox = 0;
+	int err, i, intr_ok = 0;
 
 	if (!netif_running(dev))
 		return -ENODEV;
@@ -6743,10 +6880,18 @@
 	       HOSTCC_MODE_NOW);
 
 	for (i = 0; i < 5; i++) {
+		u32 int_mbox, misc_host_ctrl;
+
 		int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 +
 					TG3_64BIT_REG_LOW);
-		if (int_mbox != 0)
+		misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
+
+		if ((int_mbox != 0) ||
+		    (misc_host_ctrl & MISC_HOST_CTRL_MASK_PCI_INT)) {
+			intr_ok = 1;
 			break;
+		}
+
 		msleep(10);
 	}
 
@@ -6759,7 +6904,7 @@
 	if (err)
 		return err;
 
-	if (int_mbox != 0)
+	if (intr_ok)
 		return 0;
 
 	return -EIO;
@@ -6936,9 +7081,10 @@
 
 		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
 			if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) {
-				u32 val = tr32(0x7c04);
+				u32 val = tr32(PCIE_TRANSACTION_CFG);
 
-				tw32(0x7c04, val | (1 << 29));
+				tw32(PCIE_TRANSACTION_CFG,
+				     val | PCIE_TRANS_CFG_1SHOT_MSI);
 			}
 		}
 	}
@@ -7857,7 +8003,7 @@
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 	if ((wol->wolopts & WAKE_MAGIC) &&
-	    tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
+	    tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
 	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
 		return -EINVAL;
 
@@ -7893,7 +8039,8 @@
 			return -EINVAL;
 		return 0;
 	}
-	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) {
+	if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
 		if (value)
 			dev->features |= NETIF_F_TSO6;
 		else
@@ -8147,6 +8294,8 @@
 
 #define NVRAM_TEST_SIZE 0x100
 #define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_HW_SIZE 0x20
+#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
 
 static int tg3_test_nvram(struct tg3 *tp)
 {
@@ -8158,12 +8307,14 @@
 
 	if (magic == TG3_EEPROM_MAGIC)
 		size = NVRAM_TEST_SIZE;
-	else if ((magic & 0xff000000) == 0xa5000000) {
+	else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
 		if ((magic & 0xe00000) == 0x200000)
 			size = NVRAM_SELFBOOT_FORMAT1_SIZE;
 		else
 			return 0;
-	} else
+	} else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
+		size = NVRAM_SELFBOOT_HW_SIZE;
+	else
 		return -EIO;
 
 	buf = kmalloc(size, GFP_KERNEL);
@@ -8182,7 +8333,8 @@
 		goto out;
 
 	/* Selfboot format */
-	if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) {
+	if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) ==
+	    TG3_EEPROM_MAGIC_FW) {
 		u8 *buf8 = (u8 *) buf, csum8 = 0;
 
 		for (i = 0; i < size; i++)
@@ -8197,6 +8349,51 @@
 		goto out;
 	}
 
+	if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) ==
+	    TG3_EEPROM_MAGIC_HW) {
+		u8 data[NVRAM_SELFBOOT_DATA_SIZE];
+	       	u8 parity[NVRAM_SELFBOOT_DATA_SIZE];
+		u8 *buf8 = (u8 *) buf;
+		int j, k;
+
+		/* Separate the parity bits and the data bytes.  */
+		for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) {
+			if ((i == 0) || (i == 8)) {
+				int l;
+				u8 msk;
+
+				for (l = 0, msk = 0x80; l < 7; l++, msk >>= 1)
+					parity[k++] = buf8[i] & msk;
+				i++;
+			}
+			else if (i == 16) {
+				int l;
+				u8 msk;
+
+				for (l = 0, msk = 0x20; l < 6; l++, msk >>= 1)
+					parity[k++] = buf8[i] & msk;
+				i++;
+
+				for (l = 0, msk = 0x80; l < 8; l++, msk >>= 1)
+					parity[k++] = buf8[i] & msk;
+				i++;
+			}
+			data[j++] = buf8[i];
+		}
+
+		err = -EIO;
+		for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) {
+			u8 hw8 = hweight8(data[i]);
+
+			if ((hw8 & 0x1) && parity[i])
+				goto out;
+			else if (!(hw8 & 0x1) && !parity[i])
+				goto out;
+		}
+		err = 0;
+		goto out;
+	}
+
 	/* Bootstrap checksum at offset 0x10 */
 	csum = calc_crc((unsigned char *) buf, 0x10);
 	if(csum != cpu_to_le32(buf[0x10/4]))
@@ -8243,7 +8440,7 @@
 /* Only test the commonly used registers */
 static int tg3_test_registers(struct tg3 *tp)
 {
-	int i, is_5705;
+	int i, is_5705, is_5750;
 	u32 offset, read_mask, write_mask, val, save_val, read_val;
 	static struct {
 		u16 offset;
@@ -8251,6 +8448,7 @@
 #define TG3_FL_5705	0x1
 #define TG3_FL_NOT_5705	0x2
 #define TG3_FL_NOT_5788	0x4
+#define TG3_FL_NOT_5750	0x8
 		u32 read_mask;
 		u32 write_mask;
 	} reg_tbl[] = {
@@ -8361,9 +8559,9 @@
 			0xffffffff, 0x00000000 },
 
 		/* Buffer Manager Control Registers. */
-		{ BUFMGR_MB_POOL_ADDR, 0x0000,
+		{ BUFMGR_MB_POOL_ADDR, TG3_FL_NOT_5750,
 			0x00000000, 0x007fff80 },
-		{ BUFMGR_MB_POOL_SIZE, 0x0000,
+		{ BUFMGR_MB_POOL_SIZE, TG3_FL_NOT_5750,
 			0x00000000, 0x007fffff },
 		{ BUFMGR_MB_RDMA_LOW_WATER, 0x0000,
 			0x00000000, 0x0000003f },
@@ -8389,10 +8587,12 @@
 		{ 0xffff, 0x0000, 0x00000000, 0x00000000 },
 	};
 
-	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+	is_5705 = is_5750 = 0;
+	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
 		is_5705 = 1;
-	else
-		is_5705 = 0;
+		if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
+			is_5750 = 1;
+	}
 
 	for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
 		if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705))
@@ -8405,6 +8605,9 @@
 		    (reg_tbl[i].flags & TG3_FL_NOT_5788))
 			continue;
 
+		if (is_5750 && (reg_tbl[i].flags & TG3_FL_NOT_5750))
+			continue;
+
 		offset = (u32) reg_tbl[i].offset;
 		read_mask = reg_tbl[i].read_mask;
 		write_mask = reg_tbl[i].write_mask;
@@ -8496,6 +8699,13 @@
 		{ 0x00008000, 0x02000},
 		{ 0x00010000, 0x0c000},
 		{ 0xffffffff, 0x00000}
+	}, mem_tbl_5906[] = {
+		{ 0x00000200, 0x00008},
+		{ 0x00004000, 0x00400},
+		{ 0x00006000, 0x00400},
+		{ 0x00008000, 0x01000},
+		{ 0x00010000, 0x01000},
+		{ 0xffffffff, 0x00000}
 	};
 	struct mem_entry *mem_tbl;
 	int err = 0;
@@ -8505,6 +8715,8 @@
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
 			mem_tbl = mem_tbl_5755;
+		else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+			mem_tbl = mem_tbl_5906;
 		else
 			mem_tbl = mem_tbl_5705;
 	} else
@@ -8541,13 +8753,41 @@
 			return 0;
 
 		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-			   MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
-			   MAC_MODE_PORT_MODE_GMII;
+			   MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY;
+		if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
+			mac_mode |= MAC_MODE_PORT_MODE_MII;
+		else
+			mac_mode |= MAC_MODE_PORT_MODE_GMII;
 		tw32(MAC_MODE, mac_mode);
 	} else if (loopback_mode == TG3_PHY_LOOPBACK) {
-		tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
-					   BMCR_SPEED1000);
+		u32 val;
+
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+			u32 phytest;
+
+			if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phytest)) {
+				u32 phy;
+
+				tg3_writephy(tp, MII_TG3_EPHY_TEST,
+					     phytest | MII_TG3_EPHY_SHADOW_EN);
+				if (!tg3_readphy(tp, 0x1b, &phy))
+					tg3_writephy(tp, 0x1b, phy & ~0x20);
+				if (!tg3_readphy(tp, 0x10, &phy))
+					tg3_writephy(tp, 0x10, phy & ~0x4000);
+				tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
+			}
+		}
+		val = BMCR_LOOPBACK | BMCR_FULLDPLX;
+		if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
+			val |= BMCR_SPEED100;
+		else
+			val |= BMCR_SPEED1000;
+
+		tg3_writephy(tp, MII_BMCR, val);
 		udelay(40);
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+			tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
+
 		/* reset to prevent losing 1st rx packet intermittently */
 		if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
 			tw32_f(MAC_RX_MODE, RX_MODE_RESET);
@@ -8555,7 +8795,11 @@
 			tw32_f(MAC_RX_MODE, tp->rx_mode);
 		}
 		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-			   MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
+			   MAC_MODE_LINK_POLARITY;
+		if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
+			mac_mode |= MAC_MODE_PORT_MODE_MII;
+		else
+			mac_mode |= MAC_MODE_PORT_MODE_GMII;
 		if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
 			mac_mode &= ~MAC_MODE_LINK_POLARITY;
 			tg3_writephy(tp, MII_TG3_EXT_CTRL,
@@ -8604,7 +8848,8 @@
 
 	udelay(10);
 
-	for (i = 0; i < 10; i++) {
+	/* 250 usec to allow enough time on some 10/100 Mbps devices.  */
+	for (i = 0; i < 25; i++) {
 		tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
 		       HOSTCC_MODE_NOW);
 
@@ -8956,7 +9201,9 @@
 	if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
 		return;
 
-	if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000))
+	if ((magic != TG3_EEPROM_MAGIC) &&
+	    ((magic & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) &&
+	    ((magic & TG3_EEPROM_MAGIC_HW_MSK) != TG3_EEPROM_MAGIC_HW))
 		return;
 
 	/*
@@ -9194,6 +9441,13 @@
 	}
 }
 
+static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+{
+	tp->nvram_jedecnum = JEDEC_ATMEL;
+	tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+	tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+}
+
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
@@ -9230,6 +9484,8 @@
 			tg3_get_5755_nvram_info(tp);
 		else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
 			tg3_get_5787_nvram_info(tp);
+		else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+			tg3_get_5906_nvram_info(tp);
 		else
 			tg3_get_nvram_info(tp);
 
@@ -9703,6 +9959,12 @@
 	/* Assume an onboard device by default.  */
 	tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM))
+			tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+		return;
+	}
+
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
 		u32 nic_cfg, led_cfg;
@@ -10034,7 +10296,10 @@
 	}
 
 out_not_found:
-	strcpy(tp->board_part_number, "none");
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+		strcpy(tp->board_part_number, "BCM95906");
+	else
+		strcpy(tp->board_part_number, "none");
 }
 
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
@@ -10236,6 +10501,7 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
 	    (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
 		tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
 
@@ -10245,7 +10511,8 @@
 
 	if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 			tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
 			tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
 		} else {
@@ -10262,7 +10529,8 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
 		tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
 
 	if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
@@ -10392,6 +10660,12 @@
 		pci_cmd &= ~PCI_COMMAND_MEMORY;
 		pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
 	}
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+		tp->read32_mbox = tg3_read32_mbox_5906;
+		tp->write32_mbox = tg3_write32_mbox_5906;
+		tp->write32_tx_mbox = tg3_write32_mbox_5906;
+		tp->write32_rx_mbox = tg3_write32_mbox_5906;
+	}
 
 	if (tp->write32 == tg3_write_indirect_reg32 ||
 	    ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
@@ -10463,6 +10737,7 @@
 	    ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
 	     (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
 	     (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) ||
 	    (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
 		tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
 
@@ -10476,7 +10751,7 @@
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
 			tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
-		else
+		else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
 			tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
 	}
 
@@ -10566,7 +10841,8 @@
 	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
 	    (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
 	     (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
-	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)))
+	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)) ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
 		tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
 
 	err = tg3_phy_probe(tp);
@@ -10617,7 +10893,8 @@
 	 * straddle the 4GB address boundary in some cases.
 	 */
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
 		tp->dev->hard_start_xmit = tg3_start_xmit;
 	else
 		tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
@@ -10698,6 +10975,8 @@
 		else
 			tg3_nvram_unlock(tp);
 	}
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+		mac_offset = 0x10;
 
 	/* First try to get it from MAC address mailbox. */
 	tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
@@ -11181,6 +11460,12 @@
 			DEFAULT_MB_MACRX_LOW_WATER_5705;
 		tp->bufmgr_config.mbuf_high_water =
 			DEFAULT_MB_HIGH_WATER_5705;
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+			tp->bufmgr_config.mbuf_mac_rx_low_water =
+				DEFAULT_MB_MACRX_LOW_WATER_5906;
+			tp->bufmgr_config.mbuf_high_water =
+				DEFAULT_MB_HIGH_WATER_5906;
+		}
 
 		tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
 			DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780;
@@ -11224,6 +11509,8 @@
 	case PHY_ID_BCM5780:	return "5780";
 	case PHY_ID_BCM5755:	return "5755";
 	case PHY_ID_BCM5787:	return "5787";
+	case PHY_ID_BCM5756:	return "5722/5756";
+	case PHY_ID_BCM5906:	return "5906";
 	case PHY_ID_BCM8002:	return "8002/serdes";
 	case 0:			return "serdes";
 	default:		return "unknown";
@@ -11526,7 +11813,8 @@
 	 */
 	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
 		dev->features |= NETIF_F_TSO;
-		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)
+		if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
+		    (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906))
 			dev->features |= NETIF_F_TSO6;
 	}
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 3ecf356..92f5300 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -24,6 +24,8 @@
 
 #define RX_COPY_THRESHOLD  		256
 
+#define TG3_RX_INTERNAL_RING_SZ_5906	32
+
 #define RX_STD_MAX_SIZE			1536
 #define RX_STD_MAX_SIZE_5705		512
 #define RX_JUMBO_MAX_SIZE		0xdeadbeef /* XXX */
@@ -129,6 +131,7 @@
 #define  CHIPREV_ID_5752_A0_HW		 0x5000
 #define  CHIPREV_ID_5752_A0		 0x6000
 #define  CHIPREV_ID_5752_A1		 0x6001
+#define  CHIPREV_ID_5906_A1		 0xc001
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -141,6 +144,7 @@
 #define   ASIC_REV_5714			 0x09
 #define   ASIC_REV_5755			 0x0a
 #define   ASIC_REV_5787			 0x0b
+#define   ASIC_REV_5906			 0x0c
 #define  GET_CHIP_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX		 0x70
 #define   CHIPREV_5700_BX		 0x71
@@ -646,7 +650,8 @@
 #define  SNDDATAI_SCTRL_FORCE_ZERO	 0x00000010
 #define SNDDATAI_STATSENAB		0x00000c0c
 #define SNDDATAI_STATSINCMASK		0x00000c10
-/* 0xc14 --> 0xc80 unused */
+#define ISO_PKT_TX			0x00000c20
+/* 0xc24 --> 0xc80 unused */
 #define SNDDATAI_COS_CNT_0		0x00000c80
 #define SNDDATAI_COS_CNT_1		0x00000c84
 #define SNDDATAI_COS_CNT_2		0x00000c88
@@ -997,11 +1002,13 @@
 #define BUFMGR_MB_MACRX_LOW_WATER	0x00004414
 #define  DEFAULT_MB_MACRX_LOW_WATER	  0x00000020
 #define  DEFAULT_MB_MACRX_LOW_WATER_5705  0x00000010
+#define  DEFAULT_MB_MACRX_LOW_WATER_5906  0x00000004
 #define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098
 #define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b
 #define BUFMGR_MB_HIGH_WATER		0x00004418
 #define  DEFAULT_MB_HIGH_WATER		 0x00000060
 #define  DEFAULT_MB_HIGH_WATER_5705	 0x00000060
+#define  DEFAULT_MB_HIGH_WATER_5906	 0x00000010
 #define  DEFAULT_MB_HIGH_WATER_JUMBO	 0x0000017c
 #define  DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096
 #define BUFMGR_RX_MB_ALLOC_REQ		0x0000441c
@@ -1138,7 +1145,12 @@
 #define TX_CPU_STATE			0x00005404
 #define TX_CPU_PGMCTR			0x0000541c
 
+#define VCPU_STATUS			0x00005100
+#define  VCPU_STATUS_INIT_DONE		 0x04000000
+#define  VCPU_STATUS_DRV_RESET		 0x08000000
+
 /* Mailboxes */
+#define GRCMBOX_BASE			0x00005600
 #define GRCMBOX_INTERRUPT_0		0x00005800 /* 64-bit */
 #define GRCMBOX_INTERRUPT_1		0x00005808 /* 64-bit */
 #define GRCMBOX_INTERRUPT_2		0x00005810 /* 64-bit */
@@ -1398,7 +1410,10 @@
 #define GRC_EEPROM_CTRL			0x00006840
 #define GRC_MDI_CTRL			0x00006844
 #define GRC_SEEPROM_DELAY		0x00006848
-/* 0x684c --> 0x6c00 unused */
+/* 0x684c --> 0x6890 unused */
+#define GRC_VCPU_EXT_CTRL		0x00006890
+#define GRC_VCPU_EXT_CTRL_HALT_CPU	 0x00400000
+#define GRC_VCPU_EXT_CTRL_DISABLE_WOL	 0x20000000
 #define GRC_FASTBOOT_PC			0x00006894	/* 5752, 5755, 5787 */
 
 /* 0x6c00 --> 0x7000 unused */
@@ -1485,9 +1500,17 @@
 #define NVRAM_WRITE1			0x00007028
 /* 0x702c --> 0x7400 unused */
 
-/* 0x7400 --> 0x8000 unused */
+/* 0x7400 --> 0x7c00 unused */
+#define PCIE_TRANSACTION_CFG		0x00007c04
+#define PCIE_TRANS_CFG_1SHOT_MSI	 0x20000000
+#define PCIE_TRANS_CFG_LOM		 0x00000020
+
 
 #define TG3_EEPROM_MAGIC		0x669955aa
+#define TG3_EEPROM_MAGIC_FW		0xa5000000
+#define TG3_EEPROM_MAGIC_FW_MSK		0xff000000
+#define TG3_EEPROM_MAGIC_HW		0xabcd
+#define TG3_EEPROM_MAGIC_HW_MSK		0xffff
 
 /* 32K Window into NIC internal memory */
 #define NIC_SRAM_WIN_BASE		0x00008000
@@ -1537,6 +1560,7 @@
 #define  FWCMD_NICDRV_FIX_DMAR		 0x00000005
 #define  FWCMD_NICDRV_FIX_DMAW		 0x00000006
 #define  FWCMD_NICDRV_ALIVE2		 0x0000000d
+#define  FWCMD_NICDRV_ALIVE3		 0x0000000e
 #define NIC_SRAM_FW_CMD_LEN_MBOX	0x00000b7c
 #define NIC_SRAM_FW_CMD_DATA_MBOX	0x00000b80
 #define NIC_SRAM_FW_ASF_STATUS_MBOX	0x00000c00
@@ -1604,6 +1628,7 @@
 #define MII_TG3_DSP_RW_PORT		0x15 /* DSP coefficient read/write port */
 
 #define MII_TG3_DSP_ADDRESS		0x17 /* DSP address register */
+#define MII_TG3_EPHY_PTEST		0x17 /* 5906 PHY register */
 
 #define MII_TG3_AUX_CTRL		0x18 /* auxilliary control register */
 
@@ -1617,6 +1642,8 @@
 #define MII_TG3_AUX_STAT_100FULL	0x0500
 #define MII_TG3_AUX_STAT_1000HALF	0x0600
 #define MII_TG3_AUX_STAT_1000FULL	0x0700
+#define MII_TG3_AUX_STAT_100		0x0008
+#define MII_TG3_AUX_STAT_FULL		0x0001
 
 #define MII_TG3_ISTAT			0x1a /* IRQ status register */
 #define MII_TG3_IMASK			0x1b /* IRQ mask register */
@@ -1627,6 +1654,9 @@
 #define MII_TG3_INT_DUPLEXCHG		0x0008
 #define MII_TG3_INT_ANEG_PAGE_RX	0x0400
 
+#define MII_TG3_EPHY_TEST		0x1f /* 5906 PHY register */
+#define MII_TG3_EPHY_SHADOW_EN		0x80
+
 /* There are two ways to manage the TX descriptors on the tigon3.
  * Either the descriptors are in host DMA'able memory, or they
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
@@ -2203,7 +2233,6 @@
 #define TG3_FLG2_PCI_EXPRESS		0x00000200
 #define TG3_FLG2_ASF_NEW_HANDSHAKE	0x00000400
 #define TG3_FLG2_HW_AUTONEG		0x00000800
-#define TG3_FLG2_PHY_JUST_INITTED	0x00001000
 #define TG3_FLG2_PHY_SERDES		0x00002000
 #define TG3_FLG2_CAPACITIVE_COUPLING	0x00004000
 #define TG3_FLG2_FLASH			0x00008000
@@ -2236,6 +2265,12 @@
 	u16				asf_counter;
 	u16				asf_multiplier;
 
+	/* 1 second counter for transient serdes link events */
+	u32				serdes_counter;
+#define SERDES_AN_TIMEOUT_5704S		2
+#define SERDES_PARALLEL_DET_TIMEOUT	1
+#define SERDES_AN_TIMEOUT_5714S		1
+
 	struct tg3_link_config		link_config;
 	struct tg3_bufmgr_config	bufmgr_config;
 
@@ -2276,6 +2311,8 @@
 #define PHY_ID_BCM5780			0x60008350
 #define PHY_ID_BCM5755			0xbc050cc0
 #define PHY_ID_BCM5787			0xbc050ce0
+#define PHY_ID_BCM5756			0xbc050ed0
+#define PHY_ID_BCM5906			0xdc00ac40
 #define PHY_ID_BCM8002			0x60010140
 #define PHY_ID_INVALID			0xffffffff
 #define PHY_ID_REV_MASK			0x0000000f
@@ -2302,7 +2339,8 @@
 	 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
 	 (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \
 	 (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
-	 (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002)
+	 (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \
+	 (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM8002)
 
 	struct tg3_hw_stats		*hw_stats;
 	dma_addr_t			stats_mapping;
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 0d66700..bfc8c3e 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -1876,7 +1876,6 @@
 		datap[size+1]=io_word & 0xff;
 	}
 
-
 	size = sprintf(buffer, "\n%6s: Adapter Address   : Node Address      : Functional Addr\n", dev->name);
 
 	size += sprintf(buffer + size,
@@ -1932,64 +1931,6 @@
 #endif
 #endif
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int streamer_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-        int i;
-	struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
-	u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
-
-	switch(cmd) {
-	case IOCTL_SISR_MASK:
-		writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
-		break;
-	case IOCTL_SPIN_LOCK_TEST:
-	        printk(KERN_INFO "spin_lock() called.\n");
-		spin_lock(&streamer_priv->streamer_lock);
-		spin_unlock(&streamer_priv->streamer_lock);
-		printk(KERN_INFO "spin_unlock() finished.\n");
-		break;
-	case IOCTL_PRINT_BDAS:
-	        printk(KERN_INFO "bdas: RXBDA: %x RXLBDA: %x TX2FDA: %x TX2LFDA: %x\n",
-		       readw(streamer_mmio + RXBDA),
-		       readw(streamer_mmio + RXLBDA),
-		       readw(streamer_mmio + TX2FDA),
-		       readw(streamer_mmio + TX2LFDA));
-		break;
-	case IOCTL_PRINT_REGISTERS:
-	        printk(KERN_INFO "registers:\n");
-		printk(KERN_INFO "SISR: %04x MISR: %04x LISR: %04x BCTL: %04x BMCTL: %04x\nmask  %04x mask  %04x\n", 
-		       readw(streamer_mmio + SISR),
-		       readw(streamer_mmio + MISR_RUM),
-		       readw(streamer_mmio + LISR),
-		       readw(streamer_mmio + BCTL),
-		       readw(streamer_mmio + BMCTL_SUM),
-		       readw(streamer_mmio + SISR_MASK),
-		       readw(streamer_mmio + MISR_MASK));
-		break;
-	case IOCTL_PRINT_RX_BUFS:
-	        printk(KERN_INFO "Print rx bufs:\n");
-		for(i=0; i<STREAMER_RX_RING_SIZE; i++)
-		        printk(KERN_INFO "rx_ring %d status: 0x%x\n", i, 
-			       streamer_priv->streamer_rx_ring[i].status);
-		break;
-	case IOCTL_PRINT_TX_BUFS:
-	        printk(KERN_INFO "Print tx bufs:\n");
-		for(i=0; i<STREAMER_TX_RING_SIZE; i++)
-		        printk(KERN_INFO "tx_ring %d status: 0x%x\n", i, 
-			       streamer_priv->streamer_tx_ring[i].status);
-		break;
-	case IOCTL_RX_CMD:
-	        streamer_rx(dev);
-		printk(KERN_INFO "Sent rx command.\n");
-		break;
-	default:
-	        printk(KERN_INFO "Bad ioctl!\n");
-	}
-	return 0;
-}
-#endif
-
 static struct pci_driver streamer_pci_driver = {
   .name     = "lanstreamer",
   .id_table = streamer_pci_tbl,
diff --git a/drivers/net/tokenring/lanstreamer.h b/drivers/net/tokenring/lanstreamer.h
index 5557d8e..e7bb349 100644
--- a/drivers/net/tokenring/lanstreamer.h
+++ b/drivers/net/tokenring/lanstreamer.h
@@ -62,18 +62,6 @@
 
 #include <linux/version.h>
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <asm/ioctl.h>
-#define IOCTL_PRINT_RX_BUFS   SIOCDEVPRIVATE
-#define IOCTL_PRINT_TX_BUFS   SIOCDEVPRIVATE+1
-#define IOCTL_RX_CMD          SIOCDEVPRIVATE+2
-#define IOCTL_TX_CMD          SIOCDEVPRIVATE+3
-#define IOCTL_PRINT_REGISTERS SIOCDEVPRIVATE+4
-#define IOCTL_PRINT_BDAS      SIOCDEVPRIVATE+5
-#define IOCTL_SPIN_LOCK_TEST  SIOCDEVPRIVATE+6
-#define IOCTL_SISR_MASK       SIOCDEVPRIVATE+7
-#endif
-
 /* MAX_INTR - the maximum number of times we can loop
  * inside the interrupt function before returning
  * control to the OS (maximum value is 256)
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 8f6f6fd..d5c32e9 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -333,11 +333,7 @@
 #define TYPHOON_RESET_TIMEOUT_NOSLEEP	((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT		((1000000 / 2) / TYPHOON_UDELAY)
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
-#define typhoon_synchronize_irq(x) synchronize_irq()
-#else
 #define typhoon_synchronize_irq(x) synchronize_irq(x)
-#endif
 
 #if defined(NETIF_F_TSO)
 #define skb_tso_size(x)		(skb_shinfo(x)->gso_size)
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 54b8e49..58b7efb 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -154,7 +154,7 @@
 	  If unsure, say N.
 
 config HDLC_RAW
-	bool "Raw HDLC support"
+	tristate "Raw HDLC support"
 	depends on HDLC
 	help
 	  Generic HDLC driver supporting raw HDLC over WAN connections.
@@ -162,7 +162,7 @@
 	  If unsure, say N.
 
 config HDLC_RAW_ETH
-	bool "Raw HDLC Ethernet device support"
+	tristate "Raw HDLC Ethernet device support"
 	depends on HDLC
 	help
 	  Generic HDLC driver supporting raw HDLC Ethernet device emulation
@@ -173,7 +173,7 @@
 	  If unsure, say N.
 
 config HDLC_CISCO
-	bool "Cisco HDLC support"
+	tristate "Cisco HDLC support"
 	depends on HDLC
 	help
 	  Generic HDLC driver supporting Cisco HDLC over WAN connections.
@@ -181,7 +181,7 @@
 	  If unsure, say N.
 
 config HDLC_FR
-	bool "Frame Relay support"
+	tristate "Frame Relay support"
 	depends on HDLC
 	help
 	  Generic HDLC driver supporting Frame Relay over WAN connections.
@@ -189,7 +189,7 @@
 	  If unsure, say N.
 
 config HDLC_PPP
-	bool "Synchronous Point-to-Point Protocol (PPP) support"
+	tristate "Synchronous Point-to-Point Protocol (PPP) support"
 	depends on HDLC
 	help
 	  Generic HDLC driver supporting PPP over WAN connections.
@@ -197,7 +197,7 @@
 	  If unsure, say N.
 
 config HDLC_X25
-	bool "X.25 protocol support"
+	tristate "X.25 protocol support"
 	depends on HDLC && (LAPB=m && HDLC=m || LAPB=y)
 	help
 	  Generic HDLC driver supporting X.25 over WAN connections.
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index 316ca68..83ec2c8 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -9,14 +9,13 @@
 cyclomx-$(CONFIG_CYCLOMX_X25)	+= cycx_x25.o
 cyclomx-objs			:= $(cyclomx-y)  
 
-hdlc-y				:= hdlc_generic.o
-hdlc-$(CONFIG_HDLC_RAW)		+= hdlc_raw.o
-hdlc-$(CONFIG_HDLC_RAW_ETH)	+= hdlc_raw_eth.o
-hdlc-$(CONFIG_HDLC_CISCO)	+= hdlc_cisco.o
-hdlc-$(CONFIG_HDLC_FR)		+= hdlc_fr.o
-hdlc-$(CONFIG_HDLC_PPP)		+= hdlc_ppp.o
-hdlc-$(CONFIG_HDLC_X25)		+= hdlc_x25.o
-hdlc-objs			:= $(hdlc-y)
+obj-$(CONFIG_HDLC)		+= hdlc.o
+obj-$(CONFIG_HDLC_RAW)		+= hdlc_raw.o
+obj-$(CONFIG_HDLC_RAW_ETH)	+= hdlc_raw_eth.o
+obj-$(CONFIG_HDLC_CISCO)	+= hdlc_cisco.o
+obj-$(CONFIG_HDLC_FR)		+= hdlc_fr.o
+obj-$(CONFIG_HDLC_PPP)		+= hdlc_ppp.o	syncppp.o
+obj-$(CONFIG_HDLC_X25)		+= hdlc_x25.o
 
 pc300-y				:= pc300_drv.o
 pc300-$(CONFIG_PC300_MLPPP)	+= pc300_tty.o
@@ -38,10 +37,6 @@
 obj-$(CONFIG_LAPBETHER)		+= lapbether.o
 obj-$(CONFIG_SBNI)		+= sbni.o
 obj-$(CONFIG_PC300)		+= pc300.o
-obj-$(CONFIG_HDLC)		+= hdlc.o
-ifeq ($(CONFIG_HDLC_PPP),y)
-  obj-$(CONFIG_HDLC)		+= syncppp.o
-endif
 obj-$(CONFIG_N2)		+= n2.o
 obj-$(CONFIG_C101)		+= c101.o
 obj-$(CONFIG_WANXL)		+= wanxl.o
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc.c
similarity index 67%
rename from drivers/net/wan/hdlc_generic.c
rename to drivers/net/wan/hdlc.c
index 04ca1f7..db354e0 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc.c
@@ -1,7 +1,7 @@
 /*
  * Generic HDLC support routines for Linux
  *
- * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -17,9 +17,9 @@
  * Use sethdlc utility to set line parameters, protocol and PVCs
  *
  * How does it work:
- * - proto.open(), close(), start(), stop() calls are serialized.
+ * - proto->open(), close(), start(), stop() calls are serialized.
  *   The order is: open, [ start, stop ... ] close ...
- * - proto.start() and stop() are called with spin_lock_irq held.
+ * - proto->start() and stop() are called with spin_lock_irq held.
  */
 
 #include <linux/module.h>
@@ -38,10 +38,12 @@
 #include <linux/hdlc.h>
 
 
-static const char* version = "HDLC support module revision 1.19";
+static const char* version = "HDLC support module revision 1.20";
 
 #undef DEBUG_LINK
 
+static struct hdlc_proto *first_proto = NULL;
+
 
 static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -63,11 +65,11 @@
 static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
 		    struct packet_type *p, struct net_device *orig_dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	if (hdlc->proto.netif_rx)
-		return hdlc->proto.netif_rx(skb);
+	struct hdlc_device_desc *desc = dev_to_desc(dev);
+	if (desc->netif_rx)
+		return desc->netif_rx(skb);
 
-	hdlc->stats.rx_dropped++; /* Shouldn't happen */
+	desc->stats.rx_dropped++; /* Shouldn't happen */
 	dev_kfree_skb(skb);
 	return NET_RX_DROP;
 }
@@ -77,8 +79,8 @@
 static inline void hdlc_proto_start(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	if (hdlc->proto.start)
-		return hdlc->proto.start(dev);
+	if (hdlc->proto->start)
+		return hdlc->proto->start(dev);
 }
 
 
@@ -86,8 +88,8 @@
 static inline void hdlc_proto_stop(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	if (hdlc->proto.stop)
-		return hdlc->proto.stop(dev);
+	if (hdlc->proto->stop)
+		return hdlc->proto->stop(dev);
 }
 
 
@@ -144,15 +146,15 @@
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
-	printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n",
+	printk(KERN_DEBUG "%s: hdlc_open() carrier %i open %i\n", dev->name,
 	       hdlc->carrier, hdlc->open);
 #endif
 
-	if (hdlc->proto.id == -1)
+	if (hdlc->proto == NULL)
 		return -ENOSYS;	/* no protocol attached */
 
-	if (hdlc->proto.open) {
-		int result = hdlc->proto.open(dev);
+	if (hdlc->proto->open) {
+		int result = hdlc->proto->open(dev);
 		if (result)
 			return result;
 	}
@@ -178,7 +180,7 @@
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
-	printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n",
+	printk(KERN_DEBUG "%s: hdlc_close() carrier %i open %i\n", dev->name,
 	       hdlc->carrier, hdlc->open);
 #endif
 
@@ -190,68 +192,34 @@
 
 	spin_unlock_irq(&hdlc->state_lock);
 
-	if (hdlc->proto.close)
-		hdlc->proto.close(dev);
+	if (hdlc->proto->close)
+		hdlc->proto->close(dev);
 }
 
 
 
-#ifndef CONFIG_HDLC_RAW
-#define hdlc_raw_ioctl(dev, ifr)	-ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_RAW_ETH
-#define hdlc_raw_eth_ioctl(dev, ifr)	-ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_PPP
-#define hdlc_ppp_ioctl(dev, ifr)	-ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_CISCO
-#define hdlc_cisco_ioctl(dev, ifr)	-ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_FR
-#define hdlc_fr_ioctl(dev, ifr)		-ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_X25
-#define hdlc_x25_ioctl(dev, ifr)	-ENOSYS
-#endif
-
-
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
-	unsigned int proto;
+	struct hdlc_proto *proto = first_proto;
+	int result;
 
 	if (cmd != SIOCWANDEV)
 		return -EINVAL;
 
-	switch(ifr->ifr_settings.type) {
-	case IF_PROTO_HDLC:
-	case IF_PROTO_HDLC_ETH:
-	case IF_PROTO_PPP:
-	case IF_PROTO_CISCO:
-	case IF_PROTO_FR:
-	case IF_PROTO_X25:
-		proto = ifr->ifr_settings.type;
-		break;
-
-	default:
-		proto = hdlc->proto.id;
+	if (dev_to_hdlc(dev)->proto) {
+		result = dev_to_hdlc(dev)->proto->ioctl(dev, ifr);
+		if (result != -EINVAL)
+			return result;
 	}
 
-	switch(proto) {
-	case IF_PROTO_HDLC:	return hdlc_raw_ioctl(dev, ifr);
-	case IF_PROTO_HDLC_ETH:	return hdlc_raw_eth_ioctl(dev, ifr);
-	case IF_PROTO_PPP:	return hdlc_ppp_ioctl(dev, ifr);
-	case IF_PROTO_CISCO:	return hdlc_cisco_ioctl(dev, ifr);
-	case IF_PROTO_FR:	return hdlc_fr_ioctl(dev, ifr);
-	case IF_PROTO_X25:	return hdlc_x25_ioctl(dev, ifr);
-	default:		return -EINVAL;
+	/* Not handled by currently attached protocol (if any) */
+
+	while (proto) {
+		if ((result = proto->ioctl(dev, ifr)) != -EINVAL)
+			return result;
+		proto = proto->next;
 	}
+	return -EINVAL;
 }
 
 void hdlc_setup(struct net_device *dev)
@@ -267,8 +235,6 @@
 
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
 
-	hdlc->proto.id = -1;
-	hdlc->proto.detach = NULL;
 	hdlc->carrier = 1;
 	hdlc->open = 0;
 	spin_lock_init(&hdlc->state_lock);
@@ -277,7 +243,8 @@
 struct net_device *alloc_hdlcdev(void *priv)
 {
 	struct net_device *dev;
-	dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
+	dev = alloc_netdev(sizeof(struct hdlc_device_desc) +
+			   sizeof(hdlc_device), "hdlc%d", hdlc_setup);
 	if (dev)
 		dev_to_hdlc(dev)->priv = priv;
 	return dev;
@@ -286,13 +253,71 @@
 void unregister_hdlc_device(struct net_device *dev)
 {
 	rtnl_lock();
-	hdlc_proto_detach(dev_to_hdlc(dev));
 	unregister_netdevice(dev);
+	detach_hdlc_protocol(dev);
 	rtnl_unlock();
 }
 
 
 
+int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
+			 int (*rx)(struct sk_buff *skb), size_t size)
+{
+	detach_hdlc_protocol(dev);
+
+	if (!try_module_get(proto->module))
+		return -ENOSYS;
+
+	if (size)
+		if ((dev_to_hdlc(dev)->state = kmalloc(size,
+						       GFP_KERNEL)) == NULL) {
+			printk(KERN_WARNING "Memory squeeze on"
+			       " hdlc_proto_attach()\n");
+			module_put(proto->module);
+			return -ENOBUFS;
+		}
+	dev_to_hdlc(dev)->proto = proto;
+	dev_to_desc(dev)->netif_rx = rx;
+	return 0;
+}
+
+
+void detach_hdlc_protocol(struct net_device *dev)
+{
+	hdlc_device *hdlc = dev_to_hdlc(dev);
+
+	if (hdlc->proto) {
+		if (hdlc->proto->detach)
+			hdlc->proto->detach(dev);
+		module_put(hdlc->proto->module);
+		hdlc->proto = NULL;
+	}
+	kfree(hdlc->state);
+	hdlc->state = NULL;
+}
+
+
+void register_hdlc_protocol(struct hdlc_proto *proto)
+{
+	proto->next = first_proto;
+	first_proto = proto;
+}
+
+
+void unregister_hdlc_protocol(struct hdlc_proto *proto)
+{
+	struct hdlc_proto **p = &first_proto;
+	while (*p) {
+		if (*p == proto) {
+			*p = proto->next;
+			return;
+		}
+		p = &((*p)->next);
+	}
+}
+
+
+
 MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
 MODULE_DESCRIPTION("HDLC support module");
 MODULE_LICENSE("GPL v2");
@@ -303,6 +328,10 @@
 EXPORT_SYMBOL(hdlc_setup);
 EXPORT_SYMBOL(alloc_hdlcdev);
 EXPORT_SYMBOL(unregister_hdlc_device);
+EXPORT_SYMBOL(register_hdlc_protocol);
+EXPORT_SYMBOL(unregister_hdlc_protocol);
+EXPORT_SYMBOL(attach_hdlc_protocol);
+EXPORT_SYMBOL(detach_hdlc_protocol);
 
 static struct packet_type hdlc_packet_type = {
 	.type = __constant_htons(ETH_P_HDLC),
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index f289dab..b0bc5dd 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Cisco HDLC support
  *
- * Copyright (C) 2000 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2000 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -34,17 +34,56 @@
 #define CISCO_KEEPALIVE_REQ	2	/* Cisco keepalive request */
 
 
+struct hdlc_header {
+	u8 address;
+	u8 control;
+	u16 protocol;
+}__attribute__ ((packed));
+
+
+struct cisco_packet {
+	u32 type;		/* code */
+	u32 par1;
+	u32 par2;
+	u16 rel;		/* reliability */
+	u32 time;
+}__attribute__ ((packed));
+#define	CISCO_PACKET_LEN	18
+#define	CISCO_BIG_PACKET_LEN	20
+
+
+struct cisco_state {
+	cisco_proto settings;
+
+	struct timer_list timer;
+	unsigned long last_poll;
+	int up;
+	int request_sent;
+	u32 txseq; /* TX sequence number */
+	u32 rxseq; /* RX sequence number */
+};
+
+
+static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
+static inline struct cisco_state * state(hdlc_device *hdlc)
+{
+	return(struct cisco_state *)(hdlc->state);
+}
+
+
 static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev,
 			     u16 type, void *daddr, void *saddr,
 			     unsigned int len)
 {
-	hdlc_header *data;
+	struct hdlc_header *data;
 #ifdef DEBUG_HARD_HEADER
 	printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name);
 #endif
 
-	skb_push(skb, sizeof(hdlc_header));
-	data = (hdlc_header*)skb->data;
+	skb_push(skb, sizeof(struct hdlc_header));
+	data = (struct hdlc_header*)skb->data;
 	if (type == CISCO_KEEPALIVE)
 		data->address = CISCO_MULTICAST;
 	else
@@ -52,7 +91,7 @@
 	data->control = 0;
 	data->protocol = htons(type);
 
-	return sizeof(hdlc_header);
+	return sizeof(struct hdlc_header);
 }
 
 
@@ -61,9 +100,10 @@
 				 u32 par1, u32 par2)
 {
 	struct sk_buff *skb;
-	cisco_packet *data;
+	struct cisco_packet *data;
 
-	skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet));
+	skb = dev_alloc_skb(sizeof(struct hdlc_header) +
+			    sizeof(struct cisco_packet));
 	if (!skb) {
 		printk(KERN_WARNING
 		       "%s: Memory squeeze on cisco_keepalive_send()\n",
@@ -72,7 +112,7 @@
 	}
 	skb_reserve(skb, 4);
 	cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
-	data = (cisco_packet*)(skb->data + 4);
+	data = (struct cisco_packet*)(skb->data + 4);
 
 	data->type = htonl(type);
 	data->par1 = htonl(par1);
@@ -81,7 +121,7 @@
 	/* we will need do_div here if 1000 % HZ != 0 */
 	data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ));
 
-	skb_put(skb, sizeof(cisco_packet));
+	skb_put(skb, sizeof(struct cisco_packet));
 	skb->priority = TC_PRIO_CONTROL;
 	skb->dev = dev;
 	skb->nh.raw = skb->data;
@@ -93,9 +133,9 @@
 
 static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-	hdlc_header *data = (hdlc_header*)skb->data;
+	struct hdlc_header *data = (struct hdlc_header*)skb->data;
 
-	if (skb->len < sizeof(hdlc_header))
+	if (skb->len < sizeof(struct hdlc_header))
 		return __constant_htons(ETH_P_HDLC);
 
 	if (data->address != CISCO_MULTICAST &&
@@ -106,7 +146,7 @@
 	case __constant_htons(ETH_P_IP):
 	case __constant_htons(ETH_P_IPX):
 	case __constant_htons(ETH_P_IPV6):
-		skb_pull(skb, sizeof(hdlc_header));
+		skb_pull(skb, sizeof(struct hdlc_header));
 		return data->protocol;
 	default:
 		return __constant_htons(ETH_P_HDLC);
@@ -118,12 +158,12 @@
 {
 	struct net_device *dev = skb->dev;
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	hdlc_header *data = (hdlc_header*)skb->data;
-	cisco_packet *cisco_data;
+	struct hdlc_header *data = (struct hdlc_header*)skb->data;
+	struct cisco_packet *cisco_data;
 	struct in_device *in_dev;
-	u32 addr, mask;
+	__be32 addr, mask;
 
-	if (skb->len < sizeof(hdlc_header))
+	if (skb->len < sizeof(struct hdlc_header))
 		goto rx_error;
 
 	if (data->address != CISCO_MULTICAST &&
@@ -137,15 +177,17 @@
 		return NET_RX_SUCCESS;
 
 	case CISCO_KEEPALIVE:
-		if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN &&
-		    skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) {
-			printk(KERN_INFO "%s: Invalid length of Cisco "
-			       "control packet (%d bytes)\n",
-			       dev->name, skb->len);
+		if ((skb->len != sizeof(struct hdlc_header) +
+		     CISCO_PACKET_LEN) &&
+		    (skb->len != sizeof(struct hdlc_header) +
+		     CISCO_BIG_PACKET_LEN)) {
+			printk(KERN_INFO "%s: Invalid length of Cisco control"
+			       " packet (%d bytes)\n", dev->name, skb->len);
 			goto rx_error;
 		}
 
-		cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header));
+		cisco_data = (struct cisco_packet*)(skb->data + sizeof
+						    (struct hdlc_header));
 
 		switch(ntohl (cisco_data->type)) {
 		case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
@@ -178,11 +220,11 @@
 			goto rx_error;
 
 		case CISCO_KEEPALIVE_REQ:
-			hdlc->state.cisco.rxseq = ntohl(cisco_data->par1);
-			if (hdlc->state.cisco.request_sent &&
-			    ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) {
-				hdlc->state.cisco.last_poll = jiffies;
-				if (!hdlc->state.cisco.up) {
+			state(hdlc)->rxseq = ntohl(cisco_data->par1);
+			if (state(hdlc)->request_sent &&
+			    ntohl(cisco_data->par2) == state(hdlc)->txseq) {
+				state(hdlc)->last_poll = jiffies;
+				if (!state(hdlc)->up) {
 					u32 sec, min, hrs, days;
 					sec = ntohl(cisco_data->time) / 1000;
 					min = sec / 60; sec -= min * 60;
@@ -193,7 +235,7 @@
 					       dev->name, days, hrs,
 					       min, sec);
 					netif_dormant_off(dev);
-					hdlc->state.cisco.up = 1;
+					state(hdlc)->up = 1;
 				}
 			}
 
@@ -208,7 +250,7 @@
 	return NET_RX_DROP;
 
  rx_error:
-	hdlc->stats.rx_errors++; /* Mark error */
+	dev_to_desc(dev)->stats.rx_errors++; /* Mark error */
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
 }
@@ -220,23 +262,22 @@
 	struct net_device *dev = (struct net_device *)arg;
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 
-	if (hdlc->state.cisco.up &&
-	    time_after(jiffies, hdlc->state.cisco.last_poll +
-		       hdlc->state.cisco.settings.timeout * HZ)) {
-		hdlc->state.cisco.up = 0;
+	if (state(hdlc)->up &&
+	    time_after(jiffies, state(hdlc)->last_poll +
+		       state(hdlc)->settings.timeout * HZ)) {
+		state(hdlc)->up = 0;
 		printk(KERN_INFO "%s: Link down\n", dev->name);
 		netif_dormant_on(dev);
 	}
 
-	cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
-			     ++hdlc->state.cisco.txseq,
-			     hdlc->state.cisco.rxseq);
-	hdlc->state.cisco.request_sent = 1;
-	hdlc->state.cisco.timer.expires = jiffies +
-		hdlc->state.cisco.settings.interval * HZ;
-	hdlc->state.cisco.timer.function = cisco_timer;
-	hdlc->state.cisco.timer.data = arg;
-	add_timer(&hdlc->state.cisco.timer);
+	cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, ++state(hdlc)->txseq,
+			     state(hdlc)->rxseq);
+	state(hdlc)->request_sent = 1;
+	state(hdlc)->timer.expires = jiffies +
+		state(hdlc)->settings.interval * HZ;
+	state(hdlc)->timer.function = cisco_timer;
+	state(hdlc)->timer.data = arg;
+	add_timer(&state(hdlc)->timer);
 }
 
 
@@ -244,15 +285,15 @@
 static void cisco_start(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	hdlc->state.cisco.up = 0;
-	hdlc->state.cisco.request_sent = 0;
-	hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0;
+	state(hdlc)->up = 0;
+	state(hdlc)->request_sent = 0;
+	state(hdlc)->txseq = state(hdlc)->rxseq = 0;
 
-	init_timer(&hdlc->state.cisco.timer);
-	hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/
-	hdlc->state.cisco.timer.function = cisco_timer;
-	hdlc->state.cisco.timer.data = (unsigned long)dev;
-	add_timer(&hdlc->state.cisco.timer);
+	init_timer(&state(hdlc)->timer);
+	state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/
+	state(hdlc)->timer.function = cisco_timer;
+	state(hdlc)->timer.data = (unsigned long)dev;
+	add_timer(&state(hdlc)->timer);
 }
 
 
@@ -260,15 +301,24 @@
 static void cisco_stop(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	del_timer_sync(&hdlc->state.cisco.timer);
+	del_timer_sync(&state(hdlc)->timer);
 	netif_dormant_on(dev);
-	hdlc->state.cisco.up = 0;
-	hdlc->state.cisco.request_sent = 0;
+	state(hdlc)->up = 0;
+	state(hdlc)->request_sent = 0;
 }
 
 
 
-int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+	.start		= cisco_start,
+	.stop		= cisco_stop,
+	.type_trans	= cisco_type_trans,
+	.ioctl		= cisco_ioctl,
+	.module		= THIS_MODULE,
+};
+ 
+ 
+static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
 	const size_t size = sizeof(cisco_proto);
@@ -278,12 +328,14 @@
 
 	switch (ifr->ifr_settings.type) {
 	case IF_GET_PROTO:
+		if (dev_to_hdlc(dev)->proto != &proto)
+			return -EINVAL;
 		ifr->ifr_settings.type = IF_PROTO_CISCO;
 		if (ifr->ifr_settings.size < size) {
 			ifr->ifr_settings.size = size; /* data size wanted */
 			return -ENOBUFS;
 		}
-		if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size))
+		if (copy_to_user(cisco_s, &state(hdlc)->settings, size))
 			return -EFAULT;
 		return 0;
 
@@ -302,19 +354,15 @@
 			return -EINVAL;
 
 		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
-
 		if (result)
 			return result;
 
-		hdlc_proto_detach(hdlc);
-		memcpy(&hdlc->state.cisco.settings, &new_settings, size);
-		memset(&hdlc->proto, 0, sizeof(hdlc->proto));
+		result = attach_hdlc_protocol(dev, &proto, cisco_rx,
+					      sizeof(struct cisco_state));
+		if (result)
+			return result;
 
-		hdlc->proto.start = cisco_start;
-		hdlc->proto.stop = cisco_stop;
-		hdlc->proto.netif_rx = cisco_rx;
-		hdlc->proto.type_trans = cisco_type_trans;
-		hdlc->proto.id = IF_PROTO_CISCO;
+		memcpy(&state(hdlc)->settings, &new_settings, size);
 		dev->hard_start_xmit = hdlc->xmit;
 		dev->hard_header = cisco_hard_header;
 		dev->hard_header_cache = NULL;
@@ -327,3 +375,25 @@
 
 	return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+	register_hdlc_protocol(&proto);
+	return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+	unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Cisco HDLC protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 7bb737b..b45ab68 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Frame Relay support
  *
- * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -52,6 +52,8 @@
 #undef DEBUG_PKT
 #undef DEBUG_ECN
 #undef DEBUG_LINK
+#undef DEBUG_PROTO
+#undef DEBUG_PVC
 
 #define FR_UI			0x03
 #define FR_PAD			0x00
@@ -115,13 +117,53 @@
 }__attribute__ ((packed)) fr_hdr;
 
 
+typedef struct pvc_device_struct {
+	struct net_device *frad;
+	struct net_device *main;
+	struct net_device *ether;	/* bridged Ethernet interface	*/
+	struct pvc_device_struct *next;	/* Sorted in ascending DLCI order */
+	int dlci;
+	int open_count;
+
+	struct {
+		unsigned int new: 1;
+		unsigned int active: 1;
+		unsigned int exist: 1;
+		unsigned int deleted: 1;
+		unsigned int fecn: 1;
+		unsigned int becn: 1;
+		unsigned int bandwidth;	/* Cisco LMI reporting only */
+	}state;
+}pvc_device;
+
+
+struct frad_state {
+	fr_proto settings;
+	pvc_device *first_pvc;
+	int dce_pvc_count;
+
+	struct timer_list timer;
+	unsigned long last_poll;
+	int reliable;
+	int dce_changed;
+	int request;
+	int fullrep_sent;
+	u32 last_errors; /* last errors bit list */
+	u8 n391cnt;
+	u8 txseq; /* TX sequence number */
+	u8 rxseq; /* RX sequence number */
+};
+
+
+static int fr_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
 static inline u16 q922_to_dlci(u8 *hdr)
 {
 	return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4);
 }
 
 
-
 static inline void dlci_to_q922(u8 *hdr, u16 dlci)
 {
 	hdr[0] = (dlci >> 2) & 0xFC;
@@ -129,10 +171,21 @@
 }
 
 
+static inline struct frad_state * state(hdlc_device *hdlc)
+{
+	return(struct frad_state *)(hdlc->state);
+}
+
+
+static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
+{
+	return dev->priv;
+}
+
 
 static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
 {
-	pvc_device *pvc = hdlc->state.fr.first_pvc;
+	pvc_device *pvc = state(hdlc)->first_pvc;
 
 	while (pvc) {
 		if (pvc->dlci == dlci)
@@ -146,10 +199,10 @@
 }
 
 
-static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
+static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc;
+	pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
 
 	while (*pvc_p) {
 		if ((*pvc_p)->dlci == dlci)
@@ -160,12 +213,15 @@
 	}
 
 	pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC);
+#ifdef DEBUG_PVC
+	printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev);
+#endif
 	if (!pvc)
 		return NULL;
 
 	memset(pvc, 0, sizeof(pvc_device));
 	pvc->dlci = dlci;
-	pvc->master = dev;
+	pvc->frad = dev;
 	pvc->next = *pvc_p;	/* Put it in the chain */
 	*pvc_p = pvc;
 	return pvc;
@@ -174,7 +230,7 @@
 
 static inline int pvc_is_used(pvc_device *pvc)
 {
-	return pvc->main != NULL || pvc->ether != NULL;
+	return pvc->main || pvc->ether;
 }
 
 
@@ -200,11 +256,14 @@
 
 static inline void delete_unused_pvcs(hdlc_device *hdlc)
 {
-	pvc_device **pvc_p = &hdlc->state.fr.first_pvc;
+	pvc_device **pvc_p = &state(hdlc)->first_pvc;
 
 	while (*pvc_p) {
 		if (!pvc_is_used(*pvc_p)) {
 			pvc_device *pvc = *pvc_p;
+#ifdef DEBUG_PVC
+			printk(KERN_DEBUG "freeing unused pvc: %p\n", pvc);
+#endif
 			*pvc_p = pvc->next;
 			kfree(pvc);
 			continue;
@@ -295,16 +354,16 @@
 {
 	pvc_device *pvc = dev_to_pvc(dev);
 
-	if ((pvc->master->flags & IFF_UP) == 0)
-		return -EIO;  /* Master must be UP in order to activate PVC */
+	if ((pvc->frad->flags & IFF_UP) == 0)
+		return -EIO;  /* Frad must be UP in order to activate PVC */
 
 	if (pvc->open_count++ == 0) {
-		hdlc_device *hdlc = dev_to_hdlc(pvc->master);
-		if (hdlc->state.fr.settings.lmi == LMI_NONE)
-			pvc->state.active = netif_carrier_ok(pvc->master);
+		hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
+		if (state(hdlc)->settings.lmi == LMI_NONE)
+			pvc->state.active = netif_carrier_ok(pvc->frad);
 
 		pvc_carrier(pvc->state.active, pvc);
-		hdlc->state.fr.dce_changed = 1;
+		state(hdlc)->dce_changed = 1;
 	}
 	return 0;
 }
@@ -316,12 +375,12 @@
 	pvc_device *pvc = dev_to_pvc(dev);
 
 	if (--pvc->open_count == 0) {
-		hdlc_device *hdlc = dev_to_hdlc(pvc->master);
-		if (hdlc->state.fr.settings.lmi == LMI_NONE)
+		hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
+		if (state(hdlc)->settings.lmi == LMI_NONE)
 			pvc->state.active = 0;
 
-		if (hdlc->state.fr.settings.dce) {
-			hdlc->state.fr.dce_changed = 1;
+		if (state(hdlc)->settings.dce) {
+			state(hdlc)->dce_changed = 1;
 			pvc->state.active = 0;
 		}
 	}
@@ -348,7 +407,7 @@
 		}
 
 		info.dlci = pvc->dlci;
-		memcpy(info.master, pvc->master->name, IFNAMSIZ);
+		memcpy(info.master, pvc->frad->name, IFNAMSIZ);
 		if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info,
 				 &info, sizeof(info)))
 			return -EFAULT;
@@ -361,7 +420,7 @@
 
 static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
 {
-	return netdev_priv(dev);
+	return &dev_to_desc(dev)->stats;
 }
 
 
@@ -393,7 +452,7 @@
 			stats->tx_packets++;
 			if (pvc->state.fecn) /* TX Congestion counter */
 				stats->tx_compressed++;
-			skb->dev = pvc->master;
+			skb->dev = pvc->frad;
 			dev_queue_xmit(skb);
 			return 0;
 		}
@@ -419,7 +478,7 @@
 static inline void fr_log_dlci_active(pvc_device *pvc)
 {
 	printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
-	       pvc->master->name,
+	       pvc->frad->name,
 	       pvc->dlci,
 	       pvc->main ? pvc->main->name : "",
 	       pvc->main && pvc->ether ? " " : "",
@@ -438,21 +497,20 @@
 }
 
 
-
 static void fr_lmi_send(struct net_device *dev, int fullrep)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	struct sk_buff *skb;
-	pvc_device *pvc = hdlc->state.fr.first_pvc;
-	int lmi = hdlc->state.fr.settings.lmi;
-	int dce = hdlc->state.fr.settings.dce;
+	pvc_device *pvc = state(hdlc)->first_pvc;
+	int lmi = state(hdlc)->settings.lmi;
+	int dce = state(hdlc)->settings.dce;
 	int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
 	int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
 	u8 *data;
 	int i = 0;
 
 	if (dce && fullrep) {
-		len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
+		len += state(hdlc)->dce_pvc_count * (2 + stat_len);
 		if (len > HDLC_MAX_MRU) {
 			printk(KERN_WARNING "%s: Too many PVCs while sending "
 			       "LMI full report\n", dev->name);
@@ -486,8 +544,9 @@
 	data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
 	data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
 	data[i++] = LMI_INTEG_LEN;
-	data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
-	data[i++] = hdlc->state.fr.rxseq;
+	data[i++] = state(hdlc)->txseq =
+		fr_lmi_nextseq(state(hdlc)->txseq);
+	data[i++] = state(hdlc)->rxseq;
 
 	if (dce && fullrep) {
 		while (pvc) {
@@ -496,7 +555,7 @@
 			data[i++] = stat_len;
 
 			/* LMI start/restart */
-			if (hdlc->state.fr.reliable && !pvc->state.exist) {
+			if (state(hdlc)->reliable && !pvc->state.exist) {
 				pvc->state.exist = pvc->state.new = 1;
 				fr_log_dlci_active(pvc);
 			}
@@ -541,15 +600,15 @@
 static void fr_set_link_state(int reliable, struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	pvc_device *pvc = hdlc->state.fr.first_pvc;
+	pvc_device *pvc = state(hdlc)->first_pvc;
 
-	hdlc->state.fr.reliable = reliable;
+	state(hdlc)->reliable = reliable;
 	if (reliable) {
 		netif_dormant_off(dev);
-		hdlc->state.fr.n391cnt = 0; /* Request full status */
-		hdlc->state.fr.dce_changed = 1;
+		state(hdlc)->n391cnt = 0; /* Request full status */
+		state(hdlc)->dce_changed = 1;
 
-		if (hdlc->state.fr.settings.lmi == LMI_NONE) {
+		if (state(hdlc)->settings.lmi == LMI_NONE) {
 			while (pvc) {	/* Activate all PVCs */
 				pvc_carrier(1, pvc);
 				pvc->state.exist = pvc->state.active = 1;
@@ -563,7 +622,7 @@
 			pvc_carrier(0, pvc);
 			pvc->state.exist = pvc->state.active = 0;
 			pvc->state.new = 0;
-			if (!hdlc->state.fr.settings.dce)
+			if (!state(hdlc)->settings.dce)
 				pvc->state.bandwidth = 0;
 			pvc = pvc->next;
 		}
@@ -571,7 +630,6 @@
 }
 
 
-
 static void fr_timer(unsigned long arg)
 {
 	struct net_device *dev = (struct net_device *)arg;
@@ -579,62 +637,61 @@
 	int i, cnt = 0, reliable;
 	u32 list;
 
-	if (hdlc->state.fr.settings.dce) {
-		reliable = hdlc->state.fr.request &&
-			time_before(jiffies, hdlc->state.fr.last_poll +
-				    hdlc->state.fr.settings.t392 * HZ);
-		hdlc->state.fr.request = 0;
+	if (state(hdlc)->settings.dce) {
+		reliable = state(hdlc)->request &&
+			time_before(jiffies, state(hdlc)->last_poll +
+				    state(hdlc)->settings.t392 * HZ);
+		state(hdlc)->request = 0;
 	} else {
-		hdlc->state.fr.last_errors <<= 1; /* Shift the list */
-		if (hdlc->state.fr.request) {
-			if (hdlc->state.fr.reliable)
+		state(hdlc)->last_errors <<= 1; /* Shift the list */
+		if (state(hdlc)->request) {
+			if (state(hdlc)->reliable)
 				printk(KERN_INFO "%s: No LMI status reply "
 				       "received\n", dev->name);
-			hdlc->state.fr.last_errors |= 1;
+			state(hdlc)->last_errors |= 1;
 		}
 
-		list = hdlc->state.fr.last_errors;
-		for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1)
+		list = state(hdlc)->last_errors;
+		for (i = 0; i < state(hdlc)->settings.n393; i++, list >>= 1)
 			cnt += (list & 1);	/* errors count */
 
-		reliable = (cnt < hdlc->state.fr.settings.n392);
+		reliable = (cnt < state(hdlc)->settings.n392);
 	}
 
-	if (hdlc->state.fr.reliable != reliable) {
+	if (state(hdlc)->reliable != reliable) {
 		printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
 		       reliable ? "" : "un");
 		fr_set_link_state(reliable, dev);
 	}
 
-	if (hdlc->state.fr.settings.dce)
-		hdlc->state.fr.timer.expires = jiffies +
-			hdlc->state.fr.settings.t392 * HZ;
+	if (state(hdlc)->settings.dce)
+		state(hdlc)->timer.expires = jiffies +
+			state(hdlc)->settings.t392 * HZ;
 	else {
-		if (hdlc->state.fr.n391cnt)
-			hdlc->state.fr.n391cnt--;
+		if (state(hdlc)->n391cnt)
+			state(hdlc)->n391cnt--;
 
-		fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0);
+		fr_lmi_send(dev, state(hdlc)->n391cnt == 0);
 
-		hdlc->state.fr.last_poll = jiffies;
-		hdlc->state.fr.request = 1;
-		hdlc->state.fr.timer.expires = jiffies +
-			hdlc->state.fr.settings.t391 * HZ;
+		state(hdlc)->last_poll = jiffies;
+		state(hdlc)->request = 1;
+		state(hdlc)->timer.expires = jiffies +
+			state(hdlc)->settings.t391 * HZ;
 	}
 
-	hdlc->state.fr.timer.function = fr_timer;
-	hdlc->state.fr.timer.data = arg;
-	add_timer(&hdlc->state.fr.timer);
+	state(hdlc)->timer.function = fr_timer;
+	state(hdlc)->timer.data = arg;
+	add_timer(&state(hdlc)->timer);
 }
 
 
-
 static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pvc_device *pvc;
 	u8 rxseq, txseq;
-	int lmi = hdlc->state.fr.settings.lmi;
-	int dce = hdlc->state.fr.settings.dce;
+	int lmi = state(hdlc)->settings.lmi;
+	int dce = state(hdlc)->settings.dce;
 	int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
 
 	if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
@@ -645,8 +702,8 @@
 
 	if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
 			     NLPID_CCITT_ANSI_LMI)) {
-		printk(KERN_INFO "%s: Received non-LMI frame with LMI"
-		       " DLCI\n", dev->name);
+		printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
+		       dev->name);
 		return 1;
 	}
 
@@ -706,53 +763,53 @@
 	}
 	i++;
 
-	hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */
+	state(hdlc)->rxseq = skb->data[i++]; /* TX sequence from peer */
 	rxseq = skb->data[i++];	/* Should confirm our sequence */
 
-	txseq = hdlc->state.fr.txseq;
+	txseq = state(hdlc)->txseq;
 
 	if (dce)
-		hdlc->state.fr.last_poll = jiffies;
+		state(hdlc)->last_poll = jiffies;
 
 	error = 0;
-	if (!hdlc->state.fr.reliable)
+	if (!state(hdlc)->reliable)
 		error = 1;
 
-	if (rxseq == 0 || rxseq != txseq) {
-		hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */
+	if (rxseq == 0 || rxseq != txseq) { /* Ask for full report next time */
+		state(hdlc)->n391cnt = 0;
 		error = 1;
 	}
 
 	if (dce) {
-		if (hdlc->state.fr.fullrep_sent && !error) {
+		if (state(hdlc)->fullrep_sent && !error) {
 /* Stop sending full report - the last one has been confirmed by DTE */
-			hdlc->state.fr.fullrep_sent = 0;
-			pvc = hdlc->state.fr.first_pvc;
+			state(hdlc)->fullrep_sent = 0;
+			pvc = state(hdlc)->first_pvc;
 			while (pvc) {
 				if (pvc->state.new) {
 					pvc->state.new = 0;
 
 /* Tell DTE that new PVC is now active */
-					hdlc->state.fr.dce_changed = 1;
+					state(hdlc)->dce_changed = 1;
 				}
 				pvc = pvc->next;
 			}
 		}
 
-		if (hdlc->state.fr.dce_changed) {
+		if (state(hdlc)->dce_changed) {
 			reptype = LMI_FULLREP;
-			hdlc->state.fr.fullrep_sent = 1;
-			hdlc->state.fr.dce_changed = 0;
+			state(hdlc)->fullrep_sent = 1;
+			state(hdlc)->dce_changed = 0;
 		}
 
-		hdlc->state.fr.request = 1; /* got request */
+		state(hdlc)->request = 1; /* got request */
 		fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
 		return 0;
 	}
 
 	/* DTE */
 
-	hdlc->state.fr.request = 0; /* got response, no request pending */
+	state(hdlc)->request = 0; /* got response, no request pending */
 
 	if (error)
 		return 0;
@@ -760,7 +817,7 @@
 	if (reptype != LMI_FULLREP)
 		return 0;
 
-	pvc = hdlc->state.fr.first_pvc;
+	pvc = state(hdlc)->first_pvc;
 
 	while (pvc) {
 		pvc->state.deleted = 1;
@@ -827,7 +884,7 @@
 		i += stat_len;
 	}
 
-	pvc = hdlc->state.fr.first_pvc;
+	pvc = state(hdlc)->first_pvc;
 
 	while (pvc) {
 		if (pvc->state.deleted && pvc->state.exist) {
@@ -841,17 +898,16 @@
 	}
 
 	/* Next full report after N391 polls */
-	hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391;
+	state(hdlc)->n391cnt = state(hdlc)->settings.n391;
 
 	return 0;
 }
 
 
-
 static int fr_rx(struct sk_buff *skb)
 {
-	struct net_device *ndev = skb->dev;
-	hdlc_device *hdlc = dev_to_hdlc(ndev);
+	struct net_device *frad = skb->dev;
+	hdlc_device *hdlc = dev_to_hdlc(frad);
 	fr_hdr *fh = (fr_hdr*)skb->data;
 	u8 *data = skb->data;
 	u16 dlci;
@@ -864,11 +920,11 @@
 	dlci = q922_to_dlci(skb->data);
 
 	if ((dlci == LMI_CCITT_ANSI_DLCI &&
-	     (hdlc->state.fr.settings.lmi == LMI_ANSI ||
-	      hdlc->state.fr.settings.lmi == LMI_CCITT)) ||
+	     (state(hdlc)->settings.lmi == LMI_ANSI ||
+	      state(hdlc)->settings.lmi == LMI_CCITT)) ||
 	    (dlci == LMI_CISCO_DLCI &&
-	     hdlc->state.fr.settings.lmi == LMI_CISCO)) {
-		if (fr_lmi_recv(ndev, skb))
+	     state(hdlc)->settings.lmi == LMI_CISCO)) {
+		if (fr_lmi_recv(frad, skb))
 			goto rx_error;
 		dev_kfree_skb_any(skb);
 		return NET_RX_SUCCESS;
@@ -878,7 +934,7 @@
 	if (!pvc) {
 #ifdef DEBUG_PKT
 		printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
-		       ndev->name, dlci);
+		       frad->name, dlci);
 #endif
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
@@ -886,7 +942,7 @@
 
 	if (pvc->state.fecn != fh->fecn) {
 #ifdef DEBUG_ECN
-		printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name,
+		printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", frad->name,
 		       dlci, fh->fecn ? "N" : "FF");
 #endif
 		pvc->state.fecn ^= 1;
@@ -894,7 +950,7 @@
 
 	if (pvc->state.becn != fh->becn) {
 #ifdef DEBUG_ECN
-		printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name,
+		printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", frad->name,
 		       dlci, fh->becn ? "N" : "FF");
 #endif
 		pvc->state.becn ^= 1;
@@ -902,7 +958,7 @@
 
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-		hdlc->stats.rx_dropped++;
+		dev_to_desc(frad)->stats.rx_dropped++;
 		return NET_RX_DROP;
 	}
 
@@ -938,13 +994,13 @@
 
 		default:
 			printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
-			       "PID=%x\n", ndev->name, oui, pid);
+			       "PID=%x\n", frad->name, oui, pid);
 			dev_kfree_skb_any(skb);
 			return NET_RX_DROP;
 		}
 	} else {
 		printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
-		       "length = %i\n", ndev->name, data[3], skb->len);
+		       "length = %i\n", frad->name, data[3], skb->len);
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
 	}
@@ -964,7 +1020,7 @@
 	}
 
  rx_error:
-	hdlc->stats.rx_errors++; /* Mark error */
+	dev_to_desc(frad)->stats.rx_errors++; /* Mark error */
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
 }
@@ -977,44 +1033,42 @@
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "fr_start\n");
 #endif
-	if (hdlc->state.fr.settings.lmi != LMI_NONE) {
-		hdlc->state.fr.reliable = 0;
-		hdlc->state.fr.dce_changed = 1;
-		hdlc->state.fr.request = 0;
-		hdlc->state.fr.fullrep_sent = 0;
-		hdlc->state.fr.last_errors = 0xFFFFFFFF;
-		hdlc->state.fr.n391cnt = 0;
-		hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0;
+	if (state(hdlc)->settings.lmi != LMI_NONE) {
+		state(hdlc)->reliable = 0;
+		state(hdlc)->dce_changed = 1;
+		state(hdlc)->request = 0;
+		state(hdlc)->fullrep_sent = 0;
+		state(hdlc)->last_errors = 0xFFFFFFFF;
+		state(hdlc)->n391cnt = 0;
+		state(hdlc)->txseq = state(hdlc)->rxseq = 0;
 
-		init_timer(&hdlc->state.fr.timer);
+		init_timer(&state(hdlc)->timer);
 		/* First poll after 1 s */
-		hdlc->state.fr.timer.expires = jiffies + HZ;
-		hdlc->state.fr.timer.function = fr_timer;
-		hdlc->state.fr.timer.data = (unsigned long)dev;
-		add_timer(&hdlc->state.fr.timer);
+		state(hdlc)->timer.expires = jiffies + HZ;
+		state(hdlc)->timer.function = fr_timer;
+		state(hdlc)->timer.data = (unsigned long)dev;
+		add_timer(&state(hdlc)->timer);
 	} else
 		fr_set_link_state(1, dev);
 }
 
 
-
 static void fr_stop(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
 	printk(KERN_DEBUG "fr_stop\n");
 #endif
-	if (hdlc->state.fr.settings.lmi != LMI_NONE)
-		del_timer_sync(&hdlc->state.fr.timer);
+	if (state(hdlc)->settings.lmi != LMI_NONE)
+		del_timer_sync(&state(hdlc)->timer);
 	fr_set_link_state(0, dev);
 }
 
 
-
 static void fr_close(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	pvc_device *pvc = hdlc->state.fr.first_pvc;
+	pvc_device *pvc = state(hdlc)->first_pvc;
 
 	while (pvc) {		/* Shutdown all PVCs for this FRAD */
 		if (pvc->main)
@@ -1025,7 +1079,8 @@
 	}
 }
 
-static void dlci_setup(struct net_device *dev)
+
+static void pvc_setup(struct net_device *dev)
 {
 	dev->type = ARPHRD_DLCI;
 	dev->flags = IFF_POINTOPOINT;
@@ -1033,9 +1088,9 @@
 	dev->addr_len = 2;
 }
 
-static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
+static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 {
-	hdlc_device *hdlc = dev_to_hdlc(master);
+	hdlc_device *hdlc = dev_to_hdlc(frad);
 	pvc_device *pvc = NULL;
 	struct net_device *dev;
 	int result, used;
@@ -1044,9 +1099,9 @@
 	if (type == ARPHRD_ETHER)
 		prefix = "pvceth%d";
 
-	if ((pvc = add_pvc(master, dlci)) == NULL) {
+	if ((pvc = add_pvc(frad, dlci)) == NULL) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
-		       master->name);
+		       frad->name);
 		return -ENOBUFS;
 	}
 
@@ -1060,11 +1115,11 @@
 				   "pvceth%d", ether_setup);
 	else
 		dev = alloc_netdev(sizeof(struct net_device_stats),
-				   "pvc%d", dlci_setup);
+				   "pvc%d", pvc_setup);
 
 	if (!dev) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
-		       master->name);
+		       frad->name);
 		delete_unused_pvcs(hdlc);
 		return -ENOBUFS;
 	}
@@ -1102,8 +1157,8 @@
 	dev->destructor = free_netdev;
 	*get_dev_p(pvc, type) = dev;
 	if (!used) {
-		hdlc->state.fr.dce_changed = 1;
-		hdlc->state.fr.dce_pvc_count++;
+		state(hdlc)->dce_changed = 1;
+		state(hdlc)->dce_pvc_count++;
 	}
 	return 0;
 }
@@ -1128,8 +1183,8 @@
 	*get_dev_p(pvc, type) = NULL;
 
 	if (!pvc_is_used(pvc)) {
-		hdlc->state.fr.dce_pvc_count--;
-		hdlc->state.fr.dce_changed = 1;
+		state(hdlc)->dce_pvc_count--;
+		state(hdlc)->dce_changed = 1;
 	}
 	delete_unused_pvcs(hdlc);
 	return 0;
@@ -1137,14 +1192,13 @@
 
 
 
-static void fr_destroy(hdlc_device *hdlc)
+static void fr_destroy(struct net_device *frad)
 {
-	pvc_device *pvc;
-
-	pvc = hdlc->state.fr.first_pvc;
-	hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */
-	hdlc->state.fr.dce_pvc_count = 0;
-	hdlc->state.fr.dce_changed = 1;
+	hdlc_device *hdlc = dev_to_hdlc(frad);
+	pvc_device *pvc = state(hdlc)->first_pvc;
+	state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */
+	state(hdlc)->dce_pvc_count = 0;
+	state(hdlc)->dce_changed = 1;
 
 	while (pvc) {
 		pvc_device *next = pvc->next;
@@ -1161,8 +1215,17 @@
 }
 
 
+static struct hdlc_proto proto = {
+	.close		= fr_close,
+	.start		= fr_start,
+	.stop		= fr_stop,
+	.detach		= fr_destroy,
+	.ioctl		= fr_ioctl,
+	.module		= THIS_MODULE,
+};
 
-int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
+
+static int fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
 	const size_t size = sizeof(fr_proto);
@@ -1173,12 +1236,14 @@
 
 	switch (ifr->ifr_settings.type) {
 	case IF_GET_PROTO:
+		if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
+			return -EINVAL;
 		ifr->ifr_settings.type = IF_PROTO_FR;
 		if (ifr->ifr_settings.size < size) {
 			ifr->ifr_settings.size = size; /* data size wanted */
 			return -ENOBUFS;
 		}
-		if (copy_to_user(fr_s, &hdlc->state.fr.settings, size))
+		if (copy_to_user(fr_s, &state(hdlc)->settings, size))
 			return -EFAULT;
 		return 0;
 
@@ -1213,20 +1278,16 @@
 		if (result)
 			return result;
 
-		if (hdlc->proto.id != IF_PROTO_FR) {
-			hdlc_proto_detach(hdlc);
-			hdlc->state.fr.first_pvc = NULL;
-			hdlc->state.fr.dce_pvc_count = 0;
+		if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */
+			result = attach_hdlc_protocol(dev, &proto, fr_rx,
+						      sizeof(struct frad_state));
+			if (result)
+				return result;
+			state(hdlc)->first_pvc = NULL;
+			state(hdlc)->dce_pvc_count = 0;
 		}
-		memcpy(&hdlc->state.fr.settings, &new_settings, size);
-		memset(&hdlc->proto, 0, sizeof(hdlc->proto));
+		memcpy(&state(hdlc)->settings, &new_settings, size);
 
-		hdlc->proto.close = fr_close;
-		hdlc->proto.start = fr_start;
-		hdlc->proto.stop = fr_stop;
-		hdlc->proto.detach = fr_destroy;
-		hdlc->proto.netif_rx = fr_rx;
-		hdlc->proto.id = IF_PROTO_FR;
 		dev->hard_start_xmit = hdlc->xmit;
 		dev->hard_header = NULL;
 		dev->type = ARPHRD_FRAD;
@@ -1238,6 +1299,9 @@
 	case IF_PROTO_FR_DEL_PVC:
 	case IF_PROTO_FR_ADD_ETH_PVC:
 	case IF_PROTO_FR_DEL_ETH_PVC:
+		if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
+			return -EINVAL;
+
 		if(!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
@@ -1263,3 +1327,24 @@
 
 	return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+	register_hdlc_protocol(&proto);
+	return 0;
+}
+
+
+static void __exit mod_exit(void)
+{
+	unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Frame-Relay protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index fbaab5b..e9f7170 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Point-to-point protocol support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -22,6 +22,21 @@
 #include <linux/lapb.h>
 #include <linux/rtnetlink.h>
 #include <linux/hdlc.h>
+#include <net/syncppp.h>
+
+struct ppp_state {
+	struct ppp_device pppdev;
+	struct ppp_device *syncppp_ptr;
+	int (*old_change_mtu)(struct net_device *dev, int new_mtu);
+};
+
+static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
+static inline struct ppp_state* state(hdlc_device *hdlc)
+{
+	return(struct ppp_state *)(hdlc->state);
+}
 
 
 static int ppp_open(struct net_device *dev)
@@ -30,16 +45,16 @@
 	void *old_ioctl;
 	int result;
 
-	dev->priv = &hdlc->state.ppp.syncppp_ptr;
-	hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev;
-	hdlc->state.ppp.pppdev.dev = dev;
+	dev->priv = &state(hdlc)->syncppp_ptr;
+	state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev;
+	state(hdlc)->pppdev.dev = dev;
 
 	old_ioctl = dev->do_ioctl;
-	hdlc->state.ppp.old_change_mtu = dev->change_mtu;
-	sppp_attach(&hdlc->state.ppp.pppdev);
+	state(hdlc)->old_change_mtu = dev->change_mtu;
+	sppp_attach(&state(hdlc)->pppdev);
 	/* sppp_attach nukes them. We don't need syncppp's ioctl */
 	dev->do_ioctl = old_ioctl;
-	hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO;
+	state(hdlc)->pppdev.sppp.pp_flags &= ~PP_CISCO;
 	dev->type = ARPHRD_PPP;
 	result = sppp_open(dev);
 	if (result) {
@@ -59,7 +74,7 @@
 	sppp_close(dev);
 	sppp_detach(dev);
 	dev->rebuild_header = NULL;
-	dev->change_mtu = hdlc->state.ppp.old_change_mtu;
+	dev->change_mtu = state(hdlc)->old_change_mtu;
 	dev->mtu = HDLC_MAX_MTU;
 	dev->hard_header_len = 16;
 }
@@ -73,13 +88,24 @@
 
 
 
-int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+	.open		= ppp_open,
+	.close		= ppp_close,
+	.type_trans	= ppp_type_trans,
+	.ioctl		= ppp_ioctl,
+	.module		= THIS_MODULE,
+};
+
+
+static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
 	case IF_GET_PROTO:
+		if (dev_to_hdlc(dev)->proto != &proto)
+			return -EINVAL;
 		ifr->ifr_settings.type = IF_PROTO_PPP;
 		return 0; /* return protocol only, no settable parameters */
 
@@ -96,13 +122,10 @@
 		if (result)
 			return result;
 
-		hdlc_proto_detach(hdlc);
-		memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-		hdlc->proto.open = ppp_open;
-		hdlc->proto.close = ppp_close;
-		hdlc->proto.type_trans = ppp_type_trans;
-		hdlc->proto.id = IF_PROTO_PPP;
+		result = attach_hdlc_protocol(dev, &proto, NULL,
+					      sizeof(struct ppp_state));
+		if (result)
+			return result;
 		dev->hard_start_xmit = hdlc->xmit;
 		dev->hard_header = NULL;
 		dev->type = ARPHRD_PPP;
@@ -113,3 +136,25 @@
 
 	return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+	register_hdlc_protocol(&proto);
+	return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+	unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("PPP protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c
index f15aa6b..fe3cae5 100644
--- a/drivers/net/wan/hdlc_raw.c
+++ b/drivers/net/wan/hdlc_raw.c
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * HDLC support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -24,6 +24,8 @@
 #include <linux/hdlc.h>
 
 
+static int raw_ioctl(struct net_device *dev, struct ifreq *ifr);
+
 static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	return __constant_htons(ETH_P_IP);
@@ -31,7 +33,14 @@
 
 
 
-int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+	.type_trans	= raw_type_trans,
+	.ioctl		= raw_ioctl,
+	.module		= THIS_MODULE,
+};
+
+
+static int raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
@@ -41,12 +50,14 @@
 
 	switch (ifr->ifr_settings.type) {
 	case IF_GET_PROTO:
+		if (dev_to_hdlc(dev)->proto != &proto)
+			return -EINVAL;
 		ifr->ifr_settings.type = IF_PROTO_HDLC;
 		if (ifr->ifr_settings.size < size) {
 			ifr->ifr_settings.size = size; /* data size wanted */
 			return -ENOBUFS;
 		}
-		if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
+		if (copy_to_user(raw_s, hdlc->state, size))
 			return -EFAULT;
 		return 0;
 
@@ -71,12 +82,11 @@
 		if (result)
 			return result;
 
-		hdlc_proto_detach(hdlc);
-		memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
-		memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-		hdlc->proto.type_trans = raw_type_trans;
-		hdlc->proto.id = IF_PROTO_HDLC;
+		result = attach_hdlc_protocol(dev, &proto, NULL,
+					      sizeof(raw_hdlc_proto));
+		if (result)
+			return result;
+		memcpy(hdlc->state, &new_settings, size);
 		dev->hard_start_xmit = hdlc->xmit;
 		dev->hard_header = NULL;
 		dev->type = ARPHRD_RAWHDLC;
@@ -88,3 +98,25 @@
 
 	return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+	register_hdlc_protocol(&proto);
+	return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+	unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Raw HDLC protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c
index d188498..1a69a9a 100644
--- a/drivers/net/wan/hdlc_raw_eth.c
+++ b/drivers/net/wan/hdlc_raw_eth.c
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * HDLC Ethernet emulation support
  *
- * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2002-2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/hdlc.h>
 
+static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
 
 static int eth_tx(struct sk_buff *skb, struct net_device *dev)
 {
@@ -44,7 +45,14 @@
 }
 
 
-int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+	.type_trans	= eth_type_trans,
+	.ioctl		= raw_eth_ioctl,
+	.module		= THIS_MODULE,
+};
+
+
+static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
 	const size_t size = sizeof(raw_hdlc_proto);
@@ -56,12 +64,14 @@
 
 	switch (ifr->ifr_settings.type) {
 	case IF_GET_PROTO:
+		if (dev_to_hdlc(dev)->proto != &proto)
+			return -EINVAL;
 		ifr->ifr_settings.type = IF_PROTO_HDLC_ETH;
 		if (ifr->ifr_settings.size < size) {
 			ifr->ifr_settings.size = size; /* data size wanted */
 			return -ENOBUFS;
 		}
-		if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
+		if (copy_to_user(raw_s, hdlc->state, size))
 			return -EFAULT;
 		return 0;
 
@@ -86,12 +96,11 @@
 		if (result)
 			return result;
 
-		hdlc_proto_detach(hdlc);
-		memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
-		memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-		hdlc->proto.type_trans = eth_type_trans;
-		hdlc->proto.id = IF_PROTO_HDLC_ETH;
+		result = attach_hdlc_protocol(dev, &proto, NULL,
+					      sizeof(raw_hdlc_proto));
+		if (result)
+			return result;
+		memcpy(hdlc->state, &new_settings, size);
 		dev->hard_start_xmit = eth_tx;
 		old_ch_mtu = dev->change_mtu;
 		old_qlen = dev->tx_queue_len;
@@ -106,3 +115,25 @@
 
 	return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+	register_hdlc_protocol(&proto);
+	return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+	unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index a867fb4..e4bb9f8 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * X.25 support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -25,6 +25,8 @@
 
 #include <net/x25device.h>
 
+static int x25_ioctl(struct net_device *dev, struct ifreq *ifr);
+
 /* These functions are callbacks called by LAPB layer */
 
 static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
@@ -162,30 +164,39 @@
 
 static int x25_rx(struct sk_buff *skb)
 {
-	hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+	struct hdlc_device_desc *desc = dev_to_desc(skb->dev);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-		hdlc->stats.rx_dropped++;
+		desc->stats.rx_dropped++;
 		return NET_RX_DROP;
 	}
 
 	if (lapb_data_received(skb->dev, skb) == LAPB_OK)
 		return NET_RX_SUCCESS;
 
-	hdlc->stats.rx_errors++;
+	desc->stats.rx_errors++;
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
 }
 
 
+static struct hdlc_proto proto = {
+	.open		= x25_open,
+	.close		= x25_close,
+	.ioctl		= x25_ioctl,
+	.module		= THIS_MODULE,
+};
 
-int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
+
+static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	int result;
 
 	switch (ifr->ifr_settings.type) {
 	case IF_GET_PROTO:
+		if (dev_to_hdlc(dev)->proto != &proto)
+			return -EINVAL;
 		ifr->ifr_settings.type = IF_PROTO_X25;
 		return 0; /* return protocol only, no settable parameters */
 
@@ -200,14 +211,9 @@
 		if (result)
 			return result;
 
-		hdlc_proto_detach(hdlc);
-		memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-		hdlc->proto.open = x25_open;
-		hdlc->proto.close = x25_close;
-		hdlc->proto.netif_rx = x25_rx;
-		hdlc->proto.type_trans = NULL;
-		hdlc->proto.id = IF_PROTO_X25;
+		if ((result = attach_hdlc_protocol(dev, &proto,
+						   x25_rx, 0)) != 0)
+			return result;
 		dev->hard_start_xmit = x25_xmit;
 		dev->hard_header = NULL;
 		dev->type = ARPHRD_X25;
@@ -218,3 +224,25 @@
 
 	return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+	register_hdlc_protocol(&proto);
+	return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+	unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("X.25 protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h
index 2024b26..63e9fcf 100644
--- a/drivers/net/wan/pc300.h
+++ b/drivers/net/wan/pc300.h
@@ -100,6 +100,7 @@
 #define	_PC300_H
 
 #include <linux/hdlc.h>
+#include <net/syncppp.h>
 #include "hd64572.h"
 #include "pc300-falc-lh.h"
 
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 56e6940..8d9b959 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -2016,7 +2016,6 @@
 			pc300ch_t *chan = &card->chan[ch];
 			pc300dev_t *d = &chan->d;
 			struct net_device *dev = d->dev;
-			hdlc_device *hdlc = dev_to_hdlc(dev);
 
 			spin_lock(&card->card_lock);
 
@@ -2049,8 +2048,8 @@
 							}
 							cpc_net_rx(dev);
 							/* Discard invalid frames */
-							hdlc->stats.rx_errors++;
-							hdlc->stats.rx_over_errors++;
+							hdlc_stats(dev)->rx_errors++;
+							hdlc_stats(dev)->rx_over_errors++;
 							chan->rx_first_bd = 0;
 							chan->rx_last_bd = N_DMA_RX_BUF - 1;
 							rx_dma_start(card, ch);
@@ -2116,8 +2115,8 @@
 										   card->hw.cpld_reg2) &
 								   ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
 						}
-						hdlc->stats.tx_errors++;
-						hdlc->stats.tx_fifo_errors++;
+						hdlc_stats(dev)->tx_errors++;
+						hdlc_stats(dev)->tx_fifo_errors++;
 						sca_tx_intr(d);
 					}
 				}
@@ -2534,7 +2533,6 @@
 
 static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
@@ -2552,10 +2550,10 @@
 		case SIOCGPC300CONF:
 #ifdef CONFIG_PC300_MLPPP
 			if (conf->proto != PC300_PROTO_MLPPP) {
-				conf->proto = hdlc->proto.id;
+				conf->proto = /* FIXME hdlc->proto.id */ 0;
 			}
 #else
-			conf->proto = hdlc->proto.id;
+			conf->proto = /* FIXME hdlc->proto.id */ 0;
 #endif
 			memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t));
 			memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t));
@@ -2588,12 +2586,12 @@
 					}
 				} else {
 					memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-					hdlc->proto.id = conf->proto;
+					/* FIXME hdlc->proto.id = conf->proto; */
 				}
 			}
 #else
 			memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-			hdlc->proto.id = conf->proto;
+			/* FIXME hdlc->proto.id = conf->proto; */
 #endif
 			return 0;
 		case SIOCGPC300STATUS:
@@ -2606,7 +2604,7 @@
 		case SIOCGPC300UTILSTATS:
 			{
 				if (!arg) {	/* clear statistics */
-					memset(&hdlc->stats, 0, sizeof(struct net_device_stats));
+					memset(hdlc_stats(dev), 0, sizeof(struct net_device_stats));
 					if (card->hw.type == PC300_TE) {
 						memset(&chan->falc, 0, sizeof(falc_t));
 					}
@@ -2617,7 +2615,7 @@
 					pc300stats.hw_type = card->hw.type;
 					pc300stats.line_on = card->chan[ch].d.line_on;
 					pc300stats.line_off = card->chan[ch].d.line_off;
-					memcpy(&pc300stats.gen_stats, &hdlc->stats,
+					memcpy(&pc300stats.gen_stats, hdlc_stats(dev),
 					       sizeof(struct net_device_stats));
 					if (card->hw.type == PC300_TE)
 						memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t));
@@ -3147,7 +3145,6 @@
 
 int cpc_open(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	struct ifreq ifr;
 	int result;
@@ -3156,12 +3153,14 @@
 	printk("pc300: cpc_open");
 #endif
 
+#ifdef FIXME
 	if (hdlc->proto.id == IF_PROTO_PPP) {
 		d->if_ptr = &hdlc->state.ppp.pppdev;
 	}
+#endif
 
 	result = hdlc_open(dev);
-	if (hdlc->proto.id == IF_PROTO_PPP) {
+	if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) {
 		dev->priv = d;
 	}
 	if (result) {
@@ -3176,7 +3175,6 @@
 
 static int cpc_close(struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
@@ -3193,7 +3191,7 @@
 	CPC_UNLOCK(card, flags);
 
 	hdlc_close(dev);
-	if (hdlc->proto.id == IF_PROTO_PPP) {
+	if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) {
 		d->if_ptr = NULL;
 	}
 #ifdef CONFIG_PC300_MLPPP
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index c13b459..218f7b5 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -469,7 +469,7 @@
 	struct net_device *dev = sp->pp_if;
 	int len = skb->len;
 	u8 *p, opt[6];
-	u32 rmagic;
+	u32 rmagic = 0;
 
 	if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
 		if (sp->pp_flags & PP_DEBUG)
@@ -763,7 +763,7 @@
 		{
 		struct in_device *in_dev;
 		struct in_ifaddr *ifa;
-		u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
+		__be32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
 #ifdef CONFIG_INET
 		rcu_read_lock();
 		if ((in_dev = __in_dev_get_rcu(dev)) != NULL)
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index bff04cb..ba737c6 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5868,7 +5868,7 @@
 		int	index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
 		/* Check the size of the string */
-		if(dwrq->length > IW_ESSID_MAX_SIZE+1) {
+		if(dwrq->length > IW_ESSID_MAX_SIZE) {
 			return -E2BIG ;
 		}
 		/* Check if index is valid */
@@ -5880,7 +5880,7 @@
 		memset(SSID_rid.ssids[index].ssid, 0,
 		       sizeof(SSID_rid.ssids[index].ssid));
 		memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
-		SSID_rid.ssids[index].len = dwrq->length - 1;
+		SSID_rid.ssids[index].len = dwrq->length;
 	}
 	SSID_rid.len = sizeof(SSID_rid);
 	/* Write it to the card */
@@ -5990,7 +5990,7 @@
 	struct airo_info *local = dev->priv;
 
 	/* Check the size of the string */
-	if(dwrq->length > 16 + 1) {
+	if(dwrq->length > 16) {
 		return -E2BIG;
 	}
 	readConfigRid(local, 1);
@@ -6015,7 +6015,7 @@
 	readConfigRid(local, 1);
 	strncpy(extra, local->config.nodeName, 16);
 	extra[16] = '\0';
-	dwrq->length = strlen(extra) + 1;
+	dwrq->length = strlen(extra);
 
 	return 0;
 }
@@ -6767,9 +6767,9 @@
 	}
 	readConfigRid(local, 1);
 	if(vwrq->flags & IW_RETRY_LIMIT) {
-		if(vwrq->flags & IW_RETRY_MAX)
+		if(vwrq->flags & IW_RETRY_LONG)
 			local->config.longRetryLimit = vwrq->value;
-		else if (vwrq->flags & IW_RETRY_MIN)
+		else if (vwrq->flags & IW_RETRY_SHORT)
 			local->config.shortRetryLimit = vwrq->value;
 		else {
 			/* No modifier : set both */
@@ -6805,14 +6805,14 @@
 	if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
 		vwrq->flags = IW_RETRY_LIFETIME;
 		vwrq->value = (int)local->config.txLifetime * 1024;
-	} else if((vwrq->flags & IW_RETRY_MAX)) {
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+	} else if((vwrq->flags & IW_RETRY_LONG)) {
+		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 		vwrq->value = (int)local->config.longRetryLimit;
 	} else {
 		vwrq->flags = IW_RETRY_LIMIT;
 		vwrq->value = (int)local->config.shortRetryLimit;
 		if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit)
-			vwrq->flags |= IW_RETRY_MIN;
+			vwrq->flags |= IW_RETRY_SHORT;
 	}
 
 	return 0;
@@ -6990,6 +6990,7 @@
 			local->config.rmode |= RXMODE_BC_MC_ADDR;
 			set_bit (FLAG_COMMIT, &local->flags);
 		case IW_POWER_ON:
+			/* This is broken, fixme ;-) */
 			break;
 		default:
 			return -EINVAL;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 995c7be..0fc267d 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1656,13 +1656,13 @@
 		priv->connect_to_any_BSS = 0;
 
 		/* Check the size of the string */
-		if (dwrq->length > MAX_SSID_LENGTH + 1)
+		if (dwrq->length > MAX_SSID_LENGTH)
 			 return -E2BIG;
 		if (index != 0)
 			return -EINVAL;
 
-		memcpy(priv->new_SSID, extra, dwrq->length - 1);
-		priv->new_SSID_size = dwrq->length - 1;
+		memcpy(priv->new_SSID, extra, dwrq->length);
+		priv->new_SSID_size = dwrq->length;
 	}
 
 	return -EINPROGRESS;
@@ -2120,9 +2120,9 @@
 	struct atmel_private *priv = netdev_priv(dev);
 
 	if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
-		if (vwrq->flags & IW_RETRY_MAX)
+		if (vwrq->flags & IW_RETRY_LONG)
 			priv->long_retry = vwrq->value;
-		else if (vwrq->flags & IW_RETRY_MIN)
+		else if (vwrq->flags & IW_RETRY_SHORT)
 			priv->short_retry = vwrq->value;
 		else {
 			/* No modifier : set both */
@@ -2144,15 +2144,15 @@
 
 	vwrq->disabled = 0;      /* Can't be disabled */
 
-	/* Note : by default, display the min retry number */
-	if (vwrq->flags & IW_RETRY_MAX) {
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+	/* Note : by default, display the short retry number */
+	if (vwrq->flags & IW_RETRY_LONG) {
+		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 		vwrq->value = priv->long_retry;
 	} else {
 		vwrq->flags = IW_RETRY_LIMIT;
 		vwrq->value = priv->short_retry;
 		if (priv->long_retry != priv->short_retry)
-			vwrq->flags |= IW_RETRY_MIN;
+			vwrq->flags |= IW_RETRY_SHORT;
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 6d4ea36..d6a8bf0 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -666,7 +666,6 @@
 };
 
 struct bcm43xx_stats {
-	u8 link_quality;
 	u8 noise;
 	struct iw_statistics wstats;
 	/* Store the last TX/RX times here for updating the leds. */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index cb9a3ae..eb65db7 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -2405,9 +2405,10 @@
 				   BCM43xx_UCODE_TIME) & 0x1f);
 
 	if ( value16 > 0x128 ) {
-		dprintk(KERN_ERR PFX
-			"Firmware: no support for microcode rev > 0x128\n");
-		err = -1;
+		printk(KERN_ERR PFX
+			"Firmware: no support for microcode extracted "
+			"from version 4.x binary drivers.\n");
+		err = -EOPNOTSUPP;
 		goto err_release_fw;
 	}
 
@@ -3169,8 +3170,7 @@
 		 * be preemtible.
 		 */
 		mutex_lock(&bcm->mutex);
-		netif_stop_queue(bcm->net_dev);
-		synchronize_net();
+		netif_tx_disable(bcm->net_dev);
 		spin_lock_irqsave(&bcm->irq_lock, flags);
 		bcm43xx_mac_suspend(bcm);
 		if (bcm43xx_using_pio(bcm))
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index eafd0f6..52ce2a9 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -361,7 +361,7 @@
 	if (phy->rev <= 2)
 		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
-	else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
+	else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
 		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
 	else
@@ -371,7 +371,7 @@
 	if (phy->rev == 2)
 		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
-	else if ((phy->rev > 2) && (phy->rev <= 7))
+	else if ((phy->rev > 2) && (phy->rev <= 8))
 		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
 			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
 	
@@ -1197,7 +1197,7 @@
 
 	if (phy->rev == 1)
 		bcm43xx_phy_initb5(bcm);
-	else if (phy->rev >= 2 && phy->rev <= 7)
+	else
 		bcm43xx_phy_initb6(bcm);
 	if (phy->rev >= 2 || phy->connected)
 		bcm43xx_phy_inita(bcm);
@@ -1241,23 +1241,22 @@
 		bcm43xx_phy_lo_g_measure(bcm);
 	} else {
 		if (radio->version == 0x2050 && radio->revision == 8) {
-			//FIXME
+			bcm43xx_radio_write16(bcm, 0x0052,
+					      (radio->txctl1 << 4) | radio->txctl2);
 		} else {
 			bcm43xx_radio_write16(bcm, 0x0052,
 					      (bcm43xx_radio_read16(bcm, 0x0052)
 					       & 0xFFF0) | radio->txctl1);
 		}
 		if (phy->rev >= 6) {
-			/*
 			bcm43xx_phy_write(bcm, 0x0036,
 					  (bcm43xx_phy_read(bcm, 0x0036)
-					   & 0xF000) | (FIXME << 12));
-			*/
+					   & 0xF000) | (radio->txctl2 << 12));
 		}
 		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
 			bcm43xx_phy_write(bcm, 0x002E, 0x8075);
 		else
-			bcm43xx_phy_write(bcm, 0x003E, 0x807F);
+			bcm43xx_phy_write(bcm, 0x002E, 0x807F);
 		if (phy->rev < 2)
 			bcm43xx_phy_write(bcm, 0x002F, 0x0101);
 		else
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 888077f..9b7b15c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -334,7 +334,7 @@
 	size_t len;
 
 	mutex_lock(&bcm->mutex);
-	len = strlen(bcm->nick) + 1;
+	len = strlen(bcm->nick);
 	memcpy(extra, bcm->nick, len);
 	data->data.length = (__u16)len;
 	data->data.flags = 1;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
index c0efbfe..0159e4e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -496,15 +496,14 @@
 	stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
 					      !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
 					      !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
-//TODO	stats.noise = 
+	stats.noise = bcm->stats.noise;
 	if (is_ofdm)
 		stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
 	else
 		stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
 	stats.received_channel = radio->channel;
-//TODO	stats.control = 
 	stats.mask = IEEE80211_STATMASK_SIGNAL |
-//TODO		     IEEE80211_STATMASK_NOISE |
+		     IEEE80211_STATMASK_NOISE |
 		     IEEE80211_STATMASK_RATE |
 		     IEEE80211_STATMASK_RSSI;
 	if (phy->type == BCM43xx_PHYTYPE_A)
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 7a49785..d061fb3 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1412,9 +1412,9 @@
 	/* what could be done, if firmware would support this.. */
 
 	if (rrq->flags & IW_RETRY_LIMIT) {
-		if (rrq->flags & IW_RETRY_MAX)
+		if (rrq->flags & IW_RETRY_LONG)
 			HFA384X_RID_LONGRETRYLIMIT = rrq->value;
-		else if (rrq->flags & IW_RETRY_MIN)
+		else if (rrq->flags & IW_RETRY_SHORT)
 			HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
 		else {
 			HFA384X_RID_LONGRETRYLIMIT = rrq->value;
@@ -1468,14 +1468,14 @@
 				rrq->value = le16_to_cpu(altretry);
 			else
 				rrq->value = local->manual_retry_count;
-		} else if ((rrq->flags & IW_RETRY_MAX)) {
-			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+		} else if ((rrq->flags & IW_RETRY_LONG)) {
+			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 			rrq->value = longretry;
 		} else {
 			rrq->flags = IW_RETRY_LIMIT;
 			rrq->value = shortretry;
 			if (shortretry != longretry)
-				rrq->flags |= IW_RETRY_MIN;
+				rrq->flags |= IW_RETRY_SHORT;
 		}
 	}
 	return 0;
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index b4d81a0..6c5add7 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -6958,7 +6958,7 @@
 	}
 
 	if (wrqu->essid.flags && wrqu->essid.length) {
-		length = wrqu->essid.length - 1;
+		length = wrqu->essid.length;
 		essid = extra;
 	}
 
@@ -7051,7 +7051,7 @@
 
 	struct ipw2100_priv *priv = ieee80211_priv(dev);
 
-	wrqu->data.length = strlen(priv->nick) + 1;
+	wrqu->data.length = strlen(priv->nick);
 	memcpy(extra, priv->nick, wrqu->data.length);
 	wrqu->data.flags = 1;	/* active */
 
@@ -7343,14 +7343,14 @@
 		goto done;
 	}
 
-	if (wrqu->retry.flags & IW_RETRY_MIN) {
+	if (wrqu->retry.flags & IW_RETRY_SHORT) {
 		err = ipw2100_set_short_retry(priv, wrqu->retry.value);
 		IPW_DEBUG_WX("SET Short Retry Limit -> %d \n",
 			     wrqu->retry.value);
 		goto done;
 	}
 
-	if (wrqu->retry.flags & IW_RETRY_MAX) {
+	if (wrqu->retry.flags & IW_RETRY_LONG) {
 		err = ipw2100_set_long_retry(priv, wrqu->retry.value);
 		IPW_DEBUG_WX("SET Long Retry Limit -> %d \n",
 			     wrqu->retry.value);
@@ -7383,14 +7383,14 @@
 	if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
 		return -EINVAL;
 
-	if (wrqu->retry.flags & IW_RETRY_MAX) {
-		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+	if (wrqu->retry.flags & IW_RETRY_LONG) {
+		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 		wrqu->retry.value = priv->long_retry_limit;
 	} else {
 		wrqu->retry.flags =
 		    (priv->short_retry_limit !=
 		     priv->long_retry_limit) ?
-		    IW_RETRY_LIMIT | IW_RETRY_MIN : IW_RETRY_LIMIT;
+		    IW_RETRY_LIMIT | IW_RETRY_SHORT : IW_RETRY_LIMIT;
 
 		wrqu->retry.value = priv->short_retry_limit;
 	}
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 7358664..5685d7b 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -8875,8 +8875,6 @@
         }
 
 	length = min((int)wrqu->essid.length, IW_ESSID_MAX_SIZE);
-	if (!extra[length - 1])
-		length--;
 
 	priv->config |= CFG_STATIC_ESSID;
 
@@ -8953,7 +8951,7 @@
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	IPW_DEBUG_WX("Getting nick\n");
 	mutex_lock(&priv->mutex);
-	wrqu->data.length = strlen(priv->nick) + 1;
+	wrqu->data.length = strlen(priv->nick);
 	memcpy(extra, priv->nick, wrqu->data.length);
 	wrqu->data.flags = 1;	/* active */
 	mutex_unlock(&priv->mutex);
@@ -9276,9 +9274,9 @@
 		return -EINVAL;
 
 	mutex_lock(&priv->mutex);
-	if (wrqu->retry.flags & IW_RETRY_MIN)
+	if (wrqu->retry.flags & IW_RETRY_SHORT)
 		priv->short_retry_limit = (u8) wrqu->retry.value;
-	else if (wrqu->retry.flags & IW_RETRY_MAX)
+	else if (wrqu->retry.flags & IW_RETRY_LONG)
 		priv->long_retry_limit = (u8) wrqu->retry.value;
 	else {
 		priv->short_retry_limit = (u8) wrqu->retry.value;
@@ -9307,11 +9305,11 @@
 		return -EINVAL;
 	}
 
-	if (wrqu->retry.flags & IW_RETRY_MAX) {
-		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+	if (wrqu->retry.flags & IW_RETRY_LONG) {
+		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 		wrqu->retry.value = priv->long_retry_limit;
-	} else if (wrqu->retry.flags & IW_RETRY_MIN) {
-		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+	} else if (wrqu->retry.flags & IW_RETRY_SHORT) {
+		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
 		wrqu->retry.value = priv->short_retry_limit;
 	} else {
 		wrqu->retry.flags = IW_RETRY_LIMIT;
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 1840b69..9e19a96 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -3037,7 +3037,7 @@
 	}
 
 	erq->flags = 1;
-	erq->length = strlen(essidbuf) + 1;
+	erq->length = strlen(essidbuf);
 
 	return 0;
 }
@@ -3078,7 +3078,7 @@
 	memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
 	orinoco_unlock(priv, &flags);
 
-	nrq->length = strlen(nickbuf)+1;
+	nrq->length = strlen(nickbuf);
 
 	return 0;
 }
@@ -3575,14 +3575,14 @@
 		rrq->value = lifetime * 1000;	/* ??? */
 	} else {
 		/* By default, display the min number */
-		if ((rrq->flags & IW_RETRY_MAX)) {
-			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+		if ((rrq->flags & IW_RETRY_LONG)) {
+			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 			rrq->value = long_limit;
 		} else {
 			rrq->flags = IW_RETRY_LIMIT;
 			rrq->value = short_limit;
 			if(short_limit != long_limit)
-				rrq->flags |= IW_RETRY_MIN;
+				rrq->flags |= IW_RETRY_SHORT;
 		}
 	}
 
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index c09fbf7..286325c 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -742,9 +742,9 @@
 
 	/* Check if we were asked for `any' */
 	if (dwrq->flags && dwrq->length) {
-		if (dwrq->length > min(33, IW_ESSID_MAX_SIZE + 1))
+		if (dwrq->length > 32)
 			return -E2BIG;
-		essid.length = dwrq->length - 1;
+		essid.length = dwrq->length;
 		memcpy(essid.octets, extra, dwrq->length);
 	} else
 		essid.length = 0;
@@ -814,7 +814,7 @@
 	dwrq->length = 0;
 
 	down_read(&priv->mib_sem);
-	dwrq->length = strlen(priv->nickname) + 1;
+	dwrq->length = strlen(priv->nickname);
 	memcpy(extra, priv->nickname, dwrq->length);
 	up_read(&priv->mib_sem);
 
@@ -992,9 +992,9 @@
 		return -EINVAL;
 
 	if (vwrq->flags & IW_RETRY_LIMIT) {
-		if (vwrq->flags & IW_RETRY_MIN)
+		if (vwrq->flags & IW_RETRY_SHORT)
 			slimit = vwrq->value;
-		else if (vwrq->flags & IW_RETRY_MAX)
+		else if (vwrq->flags & IW_RETRY_LONG)
 			llimit = vwrq->value;
 		else {
 			/* we are asked to set both */
@@ -1035,18 +1035,18 @@
 		    mgt_get_request(priv, DOT11_OID_MAXTXLIFETIME, 0, NULL, &r);
 		vwrq->value = r.u * 1024;
 		vwrq->flags = IW_RETRY_LIFETIME;
-	} else if ((vwrq->flags & IW_RETRY_MAX)) {
+	} else if ((vwrq->flags & IW_RETRY_LONG)) {
 		/* we are asked for the long retry limit */
 		rvalue |=
 		    mgt_get_request(priv, DOT11_OID_LONGRETRIES, 0, NULL, &r);
 		vwrq->value = r.u;
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 	} else {
 		/* default. get the  short retry limit */
 		rvalue |=
 		    mgt_get_request(priv, DOT11_OID_SHORTRETRIES, 0, NULL, &r);
 		vwrq->value = r.u;
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
 	}
 
 	return rvalue;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 4574290..e82548e 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -1173,7 +1173,7 @@
 		return -EOPNOTSUPP;
 	} else {
 		/* Check the size of the string */
-		if(dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+		if(dwrq->length > IW_ESSID_MAX_SIZE) {
 			return -E2BIG;
 		}
 
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index ccaf28e..337c692 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1342,7 +1342,7 @@
 	 * 'broadcast hub' radio (First byte of address being 0xFF means broadcast)
 	 */
 	if (haddr.c[0] == 0xFF) {
-		u32 brd = 0;
+		__be32 brd = 0;
 		struct in_device *in_dev;
 
 		rcu_read_lock();
@@ -1406,7 +1406,7 @@
 	int doreset = (long) jiffies - strip_info->watchdog_doreset >= 0;
 	int doprobe = (long) jiffies - strip_info->watchdog_doprobe >= 0
 	    && !doreset;
-	u32 addr, brd;
+	__be32 addr, brd;
 
 	/*
 	 * 1. If we have a packet, encapsulate it and put it in the buffer
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index e0d294c..e3ae5f6 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1802,15 +1802,15 @@
 				      &retry, sizeof(retry));
 	if (rc)
 		goto out;
-	if (wrqu->retry.flags & IW_RETRY_MAX) {
-		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+	if (wrqu->retry.flags & IW_RETRY_LONG) {
+		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
 		goto set_value;
 	}
 	rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_SHORT_RETRY_LIMIT,
 				  &retry, sizeof(retry));
 	if (rc)
 		goto out;
-	wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+	wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
 set_value:
 	wrqu->retry.value = retry;
 	wrqu->retry.disabled = 0;
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index c52e9bcf..80af9a9 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -119,7 +119,7 @@
 	switch(urb->status) {
 		case -EILSEQ:
 		case -ENODEV:
-		case -ETIMEDOUT:
+		case -ETIME:
 		case -ENOENT:
 		case -EPIPE:
 		case -EOVERFLOW:
@@ -201,7 +201,7 @@
 	switch(urb->status) {
 		case -EILSEQ:
 		case -ENODEV:
-		case -ETIMEDOUT:
+		case -ETIME:
 		case -ENOENT:
 		case -EPIPE:
 		case -EOVERFLOW:
@@ -1218,7 +1218,7 @@
 		return -EINVAL;
 	if (data->length < 1)
 		data->length = 1;
-	zd->essidlen = data->length-1;
+	zd->essidlen = data->length;
 	memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
 	memcpy(zd->essid, essid, data->length);
 	return zd1201_join(zd, zd->essid, zd->essidlen);
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 7c4e32c..aa661b2 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -249,7 +249,6 @@
 {
 	int r;
 
-	ZD_ASSERT(!mutex_is_locked(&chip->mutex));
 	mutex_lock(&chip->mutex);
 	r = zd_ioread16_locked(chip, value, addr);
 	mutex_unlock(&chip->mutex);
@@ -260,7 +259,6 @@
 {
 	int r;
 
-	ZD_ASSERT(!mutex_is_locked(&chip->mutex));
 	mutex_lock(&chip->mutex);
 	r = zd_ioread32_locked(chip, value, addr);
 	mutex_unlock(&chip->mutex);
@@ -271,7 +269,6 @@
 {
 	int r;
 
-	ZD_ASSERT(!mutex_is_locked(&chip->mutex));
 	mutex_lock(&chip->mutex);
 	r = zd_iowrite16_locked(chip, value, addr);
 	mutex_unlock(&chip->mutex);
@@ -282,7 +279,6 @@
 {
 	int r;
 
-	ZD_ASSERT(!mutex_is_locked(&chip->mutex));
 	mutex_lock(&chip->mutex);
 	r = zd_iowrite32_locked(chip, value, addr);
 	mutex_unlock(&chip->mutex);
@@ -294,7 +290,6 @@
 {
 	int r;
 
-	ZD_ASSERT(!mutex_is_locked(&chip->mutex));
 	mutex_lock(&chip->mutex);
 	r = zd_ioread32v_locked(chip, values, addresses, count);
 	mutex_unlock(&chip->mutex);
@@ -306,7 +301,6 @@
 {
 	int r;
 
-	ZD_ASSERT(!mutex_is_locked(&chip->mutex));
 	mutex_lock(&chip->mutex);
 	r = zd_iowrite32a_locked(chip, ioreqs, count);
 	mutex_unlock(&chip->mutex);
@@ -331,13 +325,22 @@
 	chip->patch_cr157 = (value >> 13) & 0x1;
 	chip->patch_6m_band_edge = (value >> 21) & 0x1;
 	chip->new_phy_layout = (value >> 31) & 0x1;
+	chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
+	chip->supports_tx_led = 1;
+	if (value & (1 << 24)) { /* LED scenario */
+		if (value & (1 << 29))
+			chip->supports_tx_led = 0;
+	}
 
 	dev_dbg_f(zd_chip_dev(chip),
 		"RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
-		"patch 6M %d new PHY %d\n",
+		"patch 6M %d new PHY %d link LED%d tx led %d\n",
 		zd_rf_name(*rf_type), *rf_type,
 		chip->pa_type, chip->patch_cck_gain,
-		chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout);
+		chip->patch_cr157, chip->patch_6m_band_edge,
+		chip->new_phy_layout,
+		chip->link_led == LED1 ? 1 : 2,
+		chip->supports_tx_led);
 	return 0;
 error:
 	*rf_type = 0;
@@ -1181,7 +1184,7 @@
 	u8 value = chip->pwr_int_values[channel - 1];
 	dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n",
 		 channel, value);
-	return zd_iowrite32_locked(chip, value, CR31);
+	return zd_iowrite16_locked(chip, value, CR31);
 }
 
 static int update_pwr_cal(struct zd_chip *chip, u8 channel)
@@ -1189,12 +1192,12 @@
 	u8 value = chip->pwr_cal_values[channel-1];
 	dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n",
 		 channel, value);
-	return zd_iowrite32_locked(chip, value, CR68);
+	return zd_iowrite16_locked(chip, value, CR68);
 }
 
 static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
 {
-	struct zd_ioreq32 ioreqs[3];
+	struct zd_ioreq16 ioreqs[3];
 
 	ioreqs[0].addr = CR67;
 	ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1];
@@ -1206,7 +1209,7 @@
 	dev_dbg_f(zd_chip_dev(chip),
 		"channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n",
 		channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value);
-	return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 static int update_channel_integration_and_calibration(struct zd_chip *chip,
@@ -1218,7 +1221,7 @@
 	if (r)
 		return r;
 	if (chip->is_zd1211b) {
-		static const struct zd_ioreq32 ioreqs[] = {
+		static const struct zd_ioreq16 ioreqs[] = {
 			{ CR69, 0x28 },
 			{},
 			{ CR69, 0x2a },
@@ -1230,7 +1233,7 @@
 		r = update_pwr_cal(chip, channel);
 		if (r)
 			return r;
-		r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+		r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
 		if (r)
 			return r;
 	}
@@ -1252,7 +1255,7 @@
 	if (r)
 		return r;
 	dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff);
-	return zd_iowrite32_locked(chip, value & 0xff, CR47);
+	return zd_iowrite16_locked(chip, value & 0xff, CR47);
 }
 
 int zd_chip_set_channel(struct zd_chip *chip, u8 channel)
@@ -1295,92 +1298,63 @@
 	return channel;
 }
 
-static u16 led_mask(int led)
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
 {
-	switch (led) {
-	case 1:
-		return LED1;
-	case 2:
-		return LED2;
-	default:
-		return 0;
-	}
-}
+	static const zd_addr_t a[] = {
+		FW_LINK_STATUS,
+		CR_LED,
+	};
 
-static int read_led_reg(struct zd_chip *chip, u16 *status)
-{
-	ZD_ASSERT(mutex_is_locked(&chip->mutex));
-	return zd_ioread16_locked(chip, status, CR_LED);
-}
+	int r;
+	u16 v[ARRAY_SIZE(a)];
+	struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = {
+		[0] = { FW_LINK_STATUS },
+		[1] = { CR_LED },
+	};
+	u16 other_led;
 
-static int write_led_reg(struct zd_chip *chip, u16 status)
-{
-	ZD_ASSERT(mutex_is_locked(&chip->mutex));
-	return zd_iowrite16_locked(chip, status, CR_LED);
-}
-
-int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status)
-{
-	int r, ret;
-	u16 mask = led_mask(led);
-	u16 reg;
-
-	if (!mask)
-		return -EINVAL;
 	mutex_lock(&chip->mutex);
-	r = read_led_reg(chip, &reg);
+	r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a));
 	if (r)
-		return r;
+		goto out;
+
+	other_led = chip->link_led == LED1 ? LED2 : LED1;
+
 	switch (status) {
-	case LED_STATUS:
-		return (reg & mask) ? LED_ON : LED_OFF;
 	case LED_OFF:
-		reg &= ~mask;
-		ret = LED_OFF;
+		ioreqs[0].value = FW_LINK_OFF;
+		ioreqs[1].value = v[1] & ~(LED1|LED2);
 		break;
-	case LED_FLIP:
-		reg ^= mask;
-		ret = (reg&mask) ? LED_ON : LED_OFF;
+	case LED_SCANNING:
+		ioreqs[0].value = FW_LINK_OFF;
+		ioreqs[1].value = v[1] & ~other_led;
+		if (get_seconds() % 3 == 0) {
+			ioreqs[1].value &= ~chip->link_led;
+		} else {
+			ioreqs[1].value |= chip->link_led;
+		}
 		break;
-	case LED_ON:
-		reg |= mask;
-		ret = LED_ON;
+	case LED_ASSOCIATED:
+		ioreqs[0].value = FW_LINK_TX;
+		ioreqs[1].value = v[1] & ~other_led;
+		ioreqs[1].value |= chip->link_led;
 		break;
 	default:
-		return -EINVAL;
-	}
-	r = write_led_reg(chip, reg);
-	if (r) {
-		ret = r;
+		r = -EINVAL;
 		goto out;
 	}
+
+	if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) {
+		r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+		if (r)
+			goto out;
+	}
+	r = 0;
 out:
 	mutex_unlock(&chip->mutex);
 	return r;
 }
 
-int zd_chip_led_flip(struct zd_chip *chip, int led,
-	const unsigned int *phases_msecs, unsigned int count)
-{
-	int i, r;
-	enum led_status status;
-
-	r = zd_chip_led_status(chip, led, LED_STATUS);
-	if (r)
-		return r;
-	status = r;
-	for (i = 0; i < count; i++) {
-		r = zd_chip_led_status(chip, led, LED_FLIP);
-		if (r < 0)
-			goto out;
-		msleep(phases_msecs[i]);
-	}
-
-out:
-	zd_chip_led_status(chip, led, status);
-	return r;
-}
-
 int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
 {
 	int r;
@@ -1679,4 +1653,3 @@
 
 	return 0;
 }
-
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 4b12508..ae59597 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -428,6 +428,7 @@
 /* masks for controlling LEDs */
 #define LED1				0x0100
 #define LED2				0x0200
+#define LED_SW				0x0400
 
 /* Seems to indicate that the configuration is over.
  */
@@ -629,6 +630,10 @@
 #define FW_SOFT_RESET           FW_REG(4)
 #define FW_FLASH_CHK            FW_REG(5)
 
+#define FW_LINK_OFF		0x0
+#define FW_LINK_TX		0x1
+/* 0x2 - link led on? */
+
 enum {
 	CR_BASE_OFFSET			= 0x9000,
 	FW_START_OFFSET			= 0xee00,
@@ -663,8 +668,11 @@
 	u8 pwr_int_values[E2P_CHANNEL_COUNT];
 	/* SetPointOFDM in the vendor driver */
 	u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
-	u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
-	   new_phy_layout:1, is_zd1211b:1;
+	u16 link_led;
+	unsigned int pa_type:4,
+		patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
+		new_phy_layout:1,
+		is_zd1211b:1, supports_tx_led:1;
 };
 
 static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -812,15 +820,12 @@
 int zd_chip_unlock_phy_regs(struct zd_chip *chip);
 
 enum led_status {
-	LED_OFF	   = 0,
-	LED_ON     = 1,
-	LED_FLIP   = 2,
-	LED_STATUS = 3,
+	LED_OFF = 0,
+	LED_SCANNING = 1,
+	LED_ASSOCIATED = 2,
 };
 
-int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status);
-int zd_chip_led_flip(struct zd_chip *chip, int led,
-	             const unsigned int *phases_msecs, unsigned int count);
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
 
 int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
 
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 1989f1c..2d12837 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -33,6 +33,10 @@
 static void ieee_init(struct ieee80211_device *ieee);
 static void softmac_init(struct ieee80211softmac_device *sm);
 
+static void housekeeping_init(struct zd_mac *mac);
+static void housekeeping_enable(struct zd_mac *mac);
+static void housekeeping_disable(struct zd_mac *mac);
+
 int zd_mac_init(struct zd_mac *mac,
 	        struct net_device *netdev,
 	        struct usb_interface *intf)
@@ -46,6 +50,7 @@
 	ieee_init(ieee);
 	softmac_init(ieee80211_priv(netdev));
 	zd_chip_init(&mac->chip, netdev, intf);
+	housekeeping_init(mac);
 	return 0;
 }
 
@@ -178,6 +183,7 @@
 	if (r < 0)
 		goto disable_rx;
 
+	housekeeping_enable(mac);
 	ieee80211softmac_start(netdev);
 	return 0;
 disable_rx:
@@ -204,6 +210,7 @@
 	 */
 
 	zd_chip_disable_rx(chip);
+	housekeeping_disable(mac);
 	ieee80211softmac_stop(netdev);
 
 	zd_chip_disable_hwint(chip);
@@ -1080,3 +1087,46 @@
 	}
 }
 #endif /* DEBUG */
+
+#define LINK_LED_WORK_DELAY HZ
+
+static void link_led_handler(void *p)
+{
+	struct zd_mac *mac = p;
+	struct zd_chip *chip = &mac->chip;
+	struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev);
+	int is_associated;
+	int r;
+
+	spin_lock_irq(&mac->lock);
+	is_associated = sm->associated != 0;
+	spin_unlock_irq(&mac->lock);
+
+	r = zd_chip_control_leds(chip,
+		                 is_associated ? LED_ASSOCIATED : LED_SCANNING);
+	if (r)
+		dev_err(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
+
+	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+		           LINK_LED_WORK_DELAY);
+}
+
+static void housekeeping_init(struct zd_mac *mac)
+{
+	INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac);
+}
+
+static void housekeeping_enable(struct zd_mac *mac)
+{
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+			   0);
+}
+
+static void housekeeping_disable(struct zd_mac *mac)
+{
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+	cancel_rearming_delayed_workqueue(zd_workqueue,
+		&mac->housekeeping.link_led_work);
+	zd_chip_control_leds(&mac->chip, LED_OFF);
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 29b51fd..b8ea3de 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -120,6 +120,10 @@
 	MAC_FIXED_CHANNEL = 0x01,
 };
 
+struct housekeeping {
+	struct work_struct link_led_work;
+};
+
 #define ZD_MAC_STATS_BUFFER_SIZE 16
 
 struct zd_mac {
@@ -128,6 +132,7 @@
 	struct net_device *netdev;
 	/* Unlocked reading possible */
 	struct iw_statistics iw_stats;
+	struct housekeeping housekeeping;
 	unsigned int stats_count;
 	u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
 	u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c
index 440ef24..af3a7b3 100644
--- a/drivers/net/wireless/zd1211rw/zd_netdev.c
+++ b/drivers/net/wireless/zd1211rw/zd_netdev.c
@@ -82,7 +82,7 @@
 		       union iwreq_data *req, char *extra)
 {
 	strcpy(extra, "zd1211");
-	req->data.length = strlen(extra) + 1;
+	req->data.length = strlen(extra);
 	req->data.flags = 1;
 	return 0;
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 31027e5..5c265ad 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -24,6 +24,7 @@
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 #include <net/ieee80211.h>
 
 #include "zd_def.h"
@@ -1112,12 +1113,20 @@
 	.disconnect	= disconnect,
 };
 
+struct workqueue_struct *zd_workqueue;
+
 static int __init usb_init(void)
 {
 	int r;
 
 	pr_debug("usb_init()\n");
 
+	zd_workqueue = create_singlethread_workqueue(driver.name);
+	if (zd_workqueue == NULL) {
+		printk(KERN_ERR "%s: couldn't create workqueue\n", driver.name);
+		return -ENOMEM;
+	}
+
 	r = usb_register(&driver);
 	if (r) {
 		printk(KERN_ERR "usb_register() failed. Error number %d\n", r);
@@ -1132,6 +1141,7 @@
 {
 	pr_debug("usb_exit()\n");
 	usb_deregister(&driver);
+	destroy_workqueue(zd_workqueue);
 }
 
 module_init(usb_init);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index ded39de..e81a2d3 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -238,4 +238,6 @@
 
 int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
 
+extern struct workqueue_struct *zd_workqueue;
+
 #endif /* _ZD_USB_H */
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 98b83a8..78c0a26 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -374,6 +374,7 @@
 	return;
 }
 
+#ifdef CONFIG_PM
 static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
 {
 	struct parport_serial_private *priv = pci_get_drvdata(dev);
@@ -407,14 +408,17 @@
 
 	return 0;
 }
+#endif
 
 static struct pci_driver parport_serial_pci_driver = {
 	.name		= "parport_serial",
 	.id_table	= parport_serial_pci_tbl,
 	.probe		= parport_serial_pci_probe,
 	.remove		= __devexit_p(parport_serial_pci_remove),
+#ifdef CONFIG_PM
 	.suspend	= parport_serial_pci_suspend,
 	.resume		= parport_serial_pci_resume,
+#endif
 };
 
 
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 33a7b72..62c804a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -27,7 +27,7 @@
 	help
 	  If you say yes here, the system time will be set using
 	  the value read from the specified RTC device. This is useful
-	  in order to avoid unnecessary fschk runs.
+	  in order to avoid unnecessary fsck runs.
 
 config RTC_HCTOSYS_DEVICE
 	string "The RTC to read the time from"
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
index 0964d1d..2558906 100644
--- a/drivers/rtc/rtc-rs5c348.c
+++ b/drivers/rtc/rtc-rs5c348.c
@@ -23,7 +23,7 @@
 #include <linux/workqueue.h>
 #include <linux/spi/spi.h>
 
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 #define RS5C348_REG_SECS	0
 #define RS5C348_REG_MINS	1
@@ -175,8 +175,15 @@
 		goto kfree_exit;
 	if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) {
 		u8 buf[2];
+		struct rtc_time tm;
 		if (ret & RS5C348_BIT_VDET)
 			dev_warn(&spi->dev, "voltage-low detected.\n");
+		if (ret & RS5C348_BIT_XSTP)
+			dev_warn(&spi->dev, "oscillator-stop detected.\n");
+		rtc_time_to_tm(0, &tm);	/* 1970/1/1 */
+		ret = rs5c348_rtc_set_time(&spi->dev, &tm);
+		if (ret < 0)
+			goto kfree_exit;
 		buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2);
 		buf[1] = 0;
 		ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 23fa0b2..9d051e5 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -63,44 +63,26 @@
  * and function code cmd.
  * In case of an exception return 3. Otherwise return result of bitwise OR of
  * resulting condition code and DIAG return code. */
-static __inline__ int
-dia250(void *iob, int cmd)
+static inline int dia250(void *iob, int cmd)
 {
+	register unsigned long reg0 asm ("0") = (unsigned long) iob;
 	typedef union {
 		struct dasd_diag_init_io init_io;
 		struct dasd_diag_rw_io rw_io;
 	} addr_type;
 	int rc;
 
-	__asm__ __volatile__(
-#ifdef CONFIG_64BIT
-		"	lghi	%0,3\n"
-		"	lgr	0,%3\n"
+	rc = 3;
+	asm volatile(
 		"	diag	0,%2,0x250\n"
 		"0:	ipm	%0\n"
 		"	srl	%0,28\n"
 		"	or	%0,1\n"
 		"1:\n"
-		".section __ex_table,\"a\"\n"
-		"	.align 8\n"
-		"	.quad  0b,1b\n"
-		".previous\n"
-#else
-		"	lhi	%0,3\n"
-		"	lr	0,%3\n"
-		"	diag	0,%2,0x250\n"
-		"0:	ipm	%0\n"
-		"	srl	%0,28\n"
-		"	or	%0,1\n"
-		"1:\n"
-		".section __ex_table,\"a\"\n"
-		"	.align 4\n"
-		"	.long 0b,1b\n"
-		".previous\n"
-#endif
-		: "=&d" (rc), "=m" (*(addr_type *) iob)
-		: "d" (cmd), "d" (iob), "m" (*(addr_type *) iob)
-		: "0", "1", "cc");
+		EX_TABLE(0b,1b)
+		: "+d" (rc), "=m" (*(addr_type *) iob)
+		: "d" (cmd), "d" (reg0), "m" (*(addr_type *) iob)
+		: "1", "cc");
 	return rc;
 }
 
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index cab2c73..a04d912 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -89,28 +89,15 @@
  */
 static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
 {
-	int cc;
+	int cc = 2;	/* return unused cc 2 if pgin traps */
 
-	__asm__ __volatile__ (
-		"   lhi   %0,2\n"  /* return unused cc 2 if pgin traps */
-		"   .insn rre,0xb22e0000,%1,%2\n"  /* pgin %1,%2 */
-                "0: ipm   %0\n"
-		"   srl   %0,28\n"
+	asm volatile(
+		"	.insn	rre,0xb22e0000,%1,%2\n"  /* pgin %1,%2 */
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
 		"1:\n"
-#ifndef CONFIG_64BIT
-		".section __ex_table,\"a\"\n"
-		"   .align 4\n"
-		"   .long  0b,1b\n"
-		".previous"
-#else
-                ".section __ex_table,\"a\"\n"
-                "   .align 8\n"
-                "   .quad 0b,1b\n"
-                ".previous"
-#endif
-		: "=&d" (cc) 
-		: "a" (__pa(page_addr)), "a" (xpage_index) 
-		: "cc" );
+		EX_TABLE(0b,1b)
+		: "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
 	if (cc == 3)
 		return -ENXIO;
 	if (cc == 2) {
@@ -137,28 +124,15 @@
  */
 static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index)
 {
-	int cc;
+	int cc = 2;	/* return unused cc 2 if pgin traps */
 
-	__asm__ __volatile__ (
-		"   lhi   %0,2\n"  /* return unused cc 2 if pgout traps */
-		"   .insn rre,0xb22f0000,%1,%2\n"  /* pgout %1,%2 */
-                "0: ipm   %0\n"
-		"   srl   %0,28\n"
+	asm volatile(
+		"	.insn	rre,0xb22f0000,%1,%2\n"  /* pgout %1,%2 */
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
 		"1:\n"
-#ifndef CONFIG_64BIT
-		".section __ex_table,\"a\"\n"
-		"   .align 4\n"
-		"   .long  0b,1b\n"
-		".previous"
-#else
-                ".section __ex_table,\"a\"\n"
-                "   .align 8\n"
-                "   .quad 0b,1b\n"
-                ".previous"
-#endif
-		: "=&d" (cc) 
-		: "a" (__pa(page_addr)), "a" (xpage_index) 
-		: "cc" );
+		EX_TABLE(0b,1b)
+		: "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
 	if (cc == 3)
 		return -ENXIO;
 	if (cc == 2) {
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index ef004d0..b4557fa 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -17,7 +17,6 @@
 
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
-#include <asm/cpcmd.h>
 #include <asm/ebcdic.h>
 #include <asm/idals.h>
 
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 985d161..31e33575 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -100,13 +100,12 @@
 {
 	int cc;
 
-	__asm__ __volatile__(
-		"   .insn rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=&d" (cc)
-		: "d" (command), "a" (__pa(sccb))
-		: "cc", "memory" );
+	asm volatile(
+		"	.insn	rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=&d" (cc) : "d" (command), "a" (__pa(sccb))
+		: "cc", "memory");
 	if (cc == 3)
 		return -EIO;
 	if (cc == 2)
@@ -360,16 +359,6 @@
 	sclp_process_queue();
 }
 
-/* Return current Time-Of-Day clock. */
-static inline u64
-sclp_get_clock(void)
-{
-	u64 result;
-
-	asm volatile ("STCK 0(%1)" : "=m" (result) : "a" (&(result)) : "cc");
-	return result;
-}
-
 /* Convert interval in jiffies to TOD ticks. */
 static inline u64
 sclp_tod_from_jiffies(unsigned long jiffies)
@@ -382,7 +371,6 @@
 void
 sclp_sync_wait(void)
 {
-	unsigned long psw_mask;
 	unsigned long flags;
 	unsigned long cr0, cr0_sync;
 	u64 timeout;
@@ -392,7 +380,7 @@
 	timeout = 0;
 	if (timer_pending(&sclp_request_timer)) {
 		/* Get timeout TOD value */
-		timeout = sclp_get_clock() +
+		timeout = get_clock() +
 			  sclp_tod_from_jiffies(sclp_request_timer.expires -
 						jiffies);
 	}
@@ -406,13 +394,12 @@
 	cr0_sync |= 0x00000200;
 	cr0_sync &= 0xFFFFF3AC;
 	__ctl_load(cr0_sync, 0, 0);
-	asm volatile ("STOSM 0(%1),0x01"
-		      : "=m" (psw_mask) : "a" (&psw_mask) : "memory");
+	__raw_local_irq_stosm(0x01);
 	/* Loop until driver state indicates finished request */
 	while (sclp_running_state != sclp_running_state_idle) {
 		/* Check for expired request timer */
 		if (timer_pending(&sclp_request_timer) &&
-		    sclp_get_clock() > timeout &&
+		    get_clock() > timeout &&
 		    del_timer(&sclp_request_timer))
 			sclp_request_timer.function(sclp_request_timer.data);
 		barrier();
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 2971804..06e2eee 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -698,7 +698,6 @@
 	if (!tp->freemem_pages)
 		goto out_tp;
 	INIT_LIST_HEAD(&tp->freemem);
-	init_timer(&tp->timer);
 	for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
 		tp->freemem_pages[pages] = (void *)
 			__get_free_pages(GFP_KERNEL|GFP_DMA, 0);
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 807320a..4b868f7 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -54,48 +54,20 @@
 static int __diag288(enum vmwdt_func func, unsigned int timeout,
 			    char *cmd, size_t len)
 {
-	register unsigned long __func asm("2");
-	register unsigned long __timeout asm("3");
-	register unsigned long __cmdp asm("4");
-	register unsigned long __cmdl asm("5");
+	register unsigned long __func asm("2") = func;
+	register unsigned long __timeout asm("3") = timeout;
+	register unsigned long __cmdp asm("4") = virt_to_phys(cmd);
+	register unsigned long __cmdl asm("5") = len;
 	int err;
 
-	__func = func;
-	__timeout = timeout;
-	__cmdp = virt_to_phys(cmd);
-	__cmdl = len;
-	err = 0;
-	asm volatile (
-#ifdef CONFIG_64BIT
-		       "diag %2,%4,0x288\n"
-		"1:	\n"
-		".section .fixup,\"ax\"\n"
-		"2:	lghi %0,%1\n"
-		"	jg 1b\n"
-		".previous\n"
-		".section __ex_table,\"a\"\n"
-		"	.align 8\n"
-		"	.quad 1b,2b\n"
-		".previous\n"
-#else
-		       "diag %2,%4,0x288\n"
-		"1:	\n"
-		".section .fixup,\"ax\"\n"
-		"2:	lhi %0,%1\n"
-		"	bras 1,3f\n"
-		"	.long 1b\n"
-		"3:	l 1,0(1)\n"
-		"	br 1\n"
-		".previous\n"
-		".section __ex_table,\"a\"\n"
-		"	.align 4\n"
-		"	.long 1b,2b\n"
-		".previous\n"
-#endif
-		: "+&d"(err)
-		: "i"(-EINVAL), "d"(__func), "d"(__timeout),
-		  "d"(__cmdp), "d"(__cmdl)
-		: "1", "cc");
+	err = -EINVAL;
+	asm volatile(
+		"	diag	%1,%3,0x288\n"
+		"0:	la	%0,0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "=d" (err) : "d"(__func), "d"(__timeout),
+		  "d"(__cmdp), "d"(__cmdl), "0" (-EINVAL) : "1", "cc");
 	return err;
 }
 
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 438db48..1398367 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -42,18 +42,15 @@
 	spin_lock_irqsave(&diag210_lock, flags);
 	diag210_tmp = *addr;
 
-	asm volatile (
-		"   lhi	  %0,-1\n"
-		"   sam31\n"
-		"   diag  %1,0,0x210\n"
-		"0: ipm	  %0\n"
-		"   srl	  %0,28\n"
-		"1: sam64\n"
-		".section __ex_table,\"a\"\n"
-		"    .align 8\n"
-		"    .quad 0b,1b\n"
-		".previous"
-		: "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory" );
+	asm volatile(
+		"	lhi	%0,-1\n"
+		"	sam31\n"
+		"	diag	%1,0,0x210\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
+		"1:	sam64\n"
+		EX_TABLE(0b,1b)
+		: "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
 
 	*addr = diag210_tmp;
 	spin_unlock_irqrestore(&diag210_lock, flags);
@@ -66,17 +63,14 @@
 {
 	int ccode;
 
-	asm volatile (
-		"   lhi	  %0,-1\n"
-		"   diag  %1,0,0x210\n"
-		"0: ipm	  %0\n"
-		"   srl	  %0,28\n"
+	asm volatile(
+		"	lhi	%0,-1\n"
+		"	diag	%1,0,0x210\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
 		"1:\n"
-		".section __ex_table,\"a\"\n"
-		"    .align 4\n"
-		"    .long 0b,1b\n"
-		".previous"
-		: "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory" );
+		EX_TABLE(0b,1b)
+		: "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
 
 	return ccode;
 }
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 95a9462..ad6d829 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -25,106 +25,74 @@
 static inline int stsch(struct subchannel_id schid,
 			    volatile struct schib *addr)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   stsch 0(%2)\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid), "a" (addr), "m" (*addr)
-		: "cc", "1" );
+	asm volatile(
+		"	stsch	0(%2)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
 	return ccode;
 }
 
 static inline int stsch_err(struct subchannel_id schid,
 				volatile struct schib *addr)
 {
-	int ccode;
+	register struct subchannel_id reg1 asm ("1") = schid;
+	int ccode = -EIO;
 
-	__asm__ __volatile__(
-		"    lhi  %0,%3\n"
-		"    lr	  1,%1\n"
-		"    stsch 0(%2)\n"
-		"0:  ipm  %0\n"
-		"    srl  %0,28\n"
+	asm volatile(
+		"	stsch	0(%2)\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
 		"1:\n"
-#ifdef CONFIG_64BIT
-		".section __ex_table,\"a\"\n"
-		"   .align 8\n"
-		"   .quad 0b,1b\n"
-		".previous"
-#else
-		".section __ex_table,\"a\"\n"
-		"   .align 4\n"
-		"   .long 0b,1b\n"
-		".previous"
-#endif
-		: "=&d" (ccode)
-		: "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
-		: "cc", "1" );
+		EX_TABLE(0b,1b)
+		: "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
 	return ccode;
 }
 
 static inline int msch(struct subchannel_id schid,
 			   volatile struct schib *addr)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   msch  0(%2)\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid), "a" (addr), "m" (*addr)
-		: "cc", "1" );
+	asm volatile(
+		"	msch	0(%2)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
 	return ccode;
 }
 
 static inline int msch_err(struct subchannel_id schid,
 			       volatile struct schib *addr)
 {
-	int ccode;
+	register struct subchannel_id reg1 asm ("1") = schid;
+	int ccode = -EIO;
 
-	__asm__ __volatile__(
-		"    lhi  %0,%3\n"
-		"    lr	  1,%1\n"
-		"    msch 0(%2)\n"
-		"0:  ipm  %0\n"
-		"    srl  %0,28\n"
+	asm volatile(
+		"	msch	0(%2)\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
 		"1:\n"
-#ifdef CONFIG_64BIT
-		".section __ex_table,\"a\"\n"
-		"   .align 8\n"
-		"   .quad 0b,1b\n"
-		".previous"
-#else
-		".section __ex_table,\"a\"\n"
-		"   .align 4\n"
-		"   .long 0b,1b\n"
-		".previous"
-#endif
-		: "=&d" (ccode)
-		: "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
-		: "cc", "1" );
+		EX_TABLE(0b,1b)
+		: "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
 	return ccode;
 }
 
 static inline int tsch(struct subchannel_id schid,
 			   volatile struct irb *addr)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   tsch  0(%2)\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid), "a" (addr), "m" (*addr)
-		: "cc", "1" );
+	asm volatile(
+		"	tsch	0(%2)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
 	return ccode;
 }
 
@@ -132,89 +100,77 @@
 {
 	int ccode;
 
-	__asm__ __volatile__(
-		"   tpi	  0(%1)\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "a" (addr), "m" (*addr)
-		: "cc", "1" );
+	asm volatile(
+		"	tpi	0(%1)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "a" (addr), "m" (*addr) : "cc");
 	return ccode;
 }
 
 static inline int ssch(struct subchannel_id schid,
 			   volatile struct orb *addr)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   ssch  0(%2)\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid), "a" (addr), "m" (*addr)
-		: "cc", "1" );
+	asm volatile(
+		"	ssch	0(%2)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
 	return ccode;
 }
 
 static inline int rsch(struct subchannel_id schid)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   rsch\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid)
-		: "cc", "1" );
+	asm volatile(
+		"	rsch\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1) : "cc");
 	return ccode;
 }
 
 static inline int csch(struct subchannel_id schid)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   csch\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid)
-		: "cc", "1" );
+	asm volatile(
+		"	csch\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1) : "cc");
 	return ccode;
 }
 
 static inline int hsch(struct subchannel_id schid)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   hsch\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid)
-		: "cc", "1" );
+	asm volatile(
+		"	hsch\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1) : "cc");
 	return ccode;
 }
 
 static inline int xsch(struct subchannel_id schid)
 {
+	register struct subchannel_id reg1 asm ("1") = schid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   .insn rre,0xb2760000,%1,0\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (schid)
-		: "cc", "1" );
+	asm volatile(
+		"	.insn	rre,0xb2760000,%1,0\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1) : "cc");
 	return ccode;
 }
 
@@ -223,41 +179,27 @@
 	typedef struct { char _[4096]; } addr_type;
 	int cc;
 
-	__asm__ __volatile__ (
-		".insn	rre,0xb25f0000,%2,0	\n\t"
-		"ipm	%0	\n\t"
-		"srl	%0,28	\n\t"
+	asm volatile(
+		"	.insn	rre,0xb25f0000,%2,0\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
 		: "=d" (cc), "=m" (*(addr_type *) chsc_area)
 		: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
-		: "cc" );
-
+		: "cc");
 	return cc;
 }
 
-static inline int iac( void)
-{
-	int ccode;
-
-	__asm__ __volatile__(
-		"   iac	  1\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode) : : "cc", "1" );
-	return ccode;
-}
-
 static inline int rchp(int chpid)
 {
+	register unsigned int reg1 asm ("1") = chpid;
 	int ccode;
 
-	__asm__ __volatile__(
-		"   lr	  1,%1\n"
-		"   rchp\n"
-		"   ipm	  %0\n"
-		"   srl	  %0,28"
-		: "=d" (ccode)
-		: "d" (chpid)
-		: "cc", "1" );
+	asm volatile(
+		"	lr	1,%1\n"
+		"	rchp\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode) : "d" (reg1) : "cc");
 	return ccode;
 }
 
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 1245693..49bb9e3 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -274,12 +274,11 @@
        register unsigned long _sch asm ("1") = sch;
        unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
 
-       asm volatile (
-              " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t"
-              : "+d" (_ccq), "+d" (_queuestart)
-              : "d" ((unsigned long)state), "d" (_sch)
-              : "memory", "cc"
-       );
+       asm volatile(
+	       "	.insn	rsy,0xeb000000008A,%1,0,0(%2)"
+	       : "+d" (_ccq), "+d" (_queuestart)
+	       : "d" ((unsigned long)state), "d" (_sch)
+	       : "memory", "cc");
        *count = _ccq & 0xff;
        *start = _queuestart & 0xff;
 
@@ -299,12 +298,11 @@
 	unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
 	unsigned long _state = 0;
 
-	asm volatile (
-	      " .insn rrf,0xB99c0000,%1,%2,0,0  \n\t"
-	      : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
-	      : "d" (_sch)
-	      : "memory", "cc"
-	);
+	asm volatile(
+		"	.insn	rrf,0xB99c0000,%1,%2,0,0"
+		: "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
+		: "d" (_sch)
+		: "memory", "cc" );
 	*count = _ccq & 0xff;
 	*start = _queuestart & 0xff;
 	*state = _state & 0xff;
@@ -319,69 +317,35 @@
 static inline int
 do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2)
 {
+	register unsigned long reg0 asm ("0") = 2;
+	register struct subchannel_id reg1 asm ("1") = schid;
+	register unsigned long reg2 asm ("2") = mask1;
+	register unsigned long reg3 asm ("3") = mask2;
 	int cc;
 
-#ifndef CONFIG_64BIT
-	asm volatile (
-		"lhi	0,2	\n\t"
-		"lr	1,%1	\n\t"
-		"lr	2,%2	\n\t"
-		"lr	3,%3	\n\t"
-		"siga   0	\n\t"
-		"ipm	%0	\n\t"
-		"srl	%0,28	\n\t"
+	asm volatile(
+		"	siga	0\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
 		: "=d" (cc)
-		: "d" (schid), "d" (mask1), "d" (mask2)
-		: "cc", "0", "1", "2", "3"
-		);
-#else /* CONFIG_64BIT */
-	asm volatile (
-		"lghi	0,2	\n\t"
-		"llgfr	1,%1	\n\t"
-		"llgfr	2,%2	\n\t"
-		"llgfr	3,%3	\n\t"
-		"siga   0	\n\t"
-		"ipm	%0	\n\t"
-		"srl	%0,28	\n\t"
-		: "=d" (cc)
-		: "d" (schid), "d" (mask1), "d" (mask2)
-		: "cc", "0", "1", "2", "3"
-		);
-#endif /* CONFIG_64BIT */
+		: "d" (reg0), "d" (reg1), "d" (reg2), "d" (reg3) : "cc");
 	return cc;
 }
 
 static inline int
 do_siga_input(struct subchannel_id schid, unsigned int mask)
 {
+	register unsigned long reg0 asm ("0") = 1;
+	register struct subchannel_id reg1 asm ("1") = schid;
+	register unsigned long reg2 asm ("2") = mask;
 	int cc;
 
-#ifndef CONFIG_64BIT
-	asm volatile (
-		"lhi	0,1	\n\t"
-		"lr	1,%1	\n\t"
-		"lr	2,%2	\n\t"
-		"siga   0	\n\t"
-		"ipm	%0	\n\t"
-		"srl	%0,28	\n\t"
+	asm volatile(
+		"	siga	0\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
 		: "=d" (cc)
-		: "d" (schid), "d" (mask)
-		: "cc", "0", "1", "2", "memory"
-		);
-#else /* CONFIG_64BIT */
-	asm volatile (
-		"lghi	0,1	\n\t"
-		"llgfr	1,%1	\n\t"
-		"llgfr	2,%2	\n\t"
-		"siga   0	\n\t"
-		"ipm	%0	\n\t"
-		"srl	%0,28	\n\t"
-		: "=d" (cc)
-		: "d" (schid), "d" (mask)
-		: "cc", "0", "1", "2", "memory"
-		);
-#endif /* CONFIG_64BIT */
-	
+		: "d" (reg0), "d" (reg1), "d" (reg2) : "cc", "memory");
 	return cc;
 }
 
@@ -389,93 +353,35 @@
 do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb,
 	       unsigned int fc)
 {
+	register unsigned long __fc asm("0") = fc;
+	register unsigned long __schid asm("1") = schid;
+	register unsigned long __mask asm("2") = mask;
 	int cc;
-	__u32 busy_bit;
 
-#ifndef CONFIG_64BIT
-	asm volatile (
-		"lhi	0,0	\n\t"
-		"lr	1,%2	\n\t"
-		"lr	2,%3	\n\t"
-		"siga	0	\n\t"
-		"0:"
-		"ipm	%0	\n\t"
-		"srl	%0,28	\n\t"
-		"srl	0,31	\n\t"
-		"lr	%1,0	\n\t"
-		"1:	\n\t"
-		".section .fixup,\"ax\"\n\t"
-		"2:	\n\t"
-		"lhi	%0,%4	\n\t"
-		"bras	1,3f	\n\t"
-		".long 1b	\n\t"
-		"3:	\n\t"
-		"l	1,0(1)	\n\t"
-		"br	1	\n\t"
-		".previous	\n\t"
-		".section __ex_table,\"a\"\n\t"
-		".align 4	\n\t"
-		".long	0b,2b	\n\t"
-		".previous	\n\t"
-		: "=d" (cc), "=d" (busy_bit)
-		: "d" (schid), "d" (mask),
-		"i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
-		: "cc", "0", "1", "2", "memory"
-		);
-#else /* CONFIG_64BIT */
-	asm volatile (
-        	"llgfr  0,%5    \n\t"
-                "lgr    1,%2    \n\t"
-		"llgfr	2,%3	\n\t"
-		"siga	0	\n\t"
-		"0:"
-		"ipm	%0	\n\t"
-		"srl	%0,28	\n\t"
-		"srl	0,31	\n\t"
-		"llgfr	%1,0	\n\t"
-		"1:	\n\t"
-		".section .fixup,\"ax\"\n\t"
-		"lghi	%0,%4	\n\t"
-		"jg	1b	\n\t"
-		".previous\n\t"
-		".section __ex_table,\"a\"\n\t"
-		".align 8	\n\t"
-		".quad	0b,1b	\n\t"
-		".previous	\n\t"
-		: "=d" (cc), "=d" (busy_bit)
-		: "d" (schid), "d" (mask),
-		"i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc)
-		: "cc", "0", "1", "2", "memory"
-		);
-#endif /* CONFIG_64BIT */
-	
-	(*bb) = busy_bit;
+	asm volatile(
+		"	siga	0\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "=d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask)
+		: "0" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
+		: "cc", "memory");
+	(*bb) = ((unsigned int) __fc) >> 31;
 	return cc;
 }
 
 static inline unsigned long
 do_clear_global_summary(void)
 {
+	register unsigned long __fn asm("1") = 3;
+	register unsigned long __tmp asm("2");
+	register unsigned long __time asm("3");
 
-	unsigned long time;
-
-#ifndef CONFIG_64BIT
-	asm volatile (
-		"lhi	1,3	\n\t"
-		".insn	rre,0xb2650000,2,0	\n\t"
-		"lr	%0,3	\n\t"
-		: "=d" (time) : : "cc", "1", "2", "3"
-		);
-#else /* CONFIG_64BIT */
-	asm volatile (
-		"lghi	1,3	\n\t"
-		".insn	rre,0xb2650000,2,0	\n\t"
-		"lgr	%0,3	\n\t"
-		: "=d" (time) : : "cc", "1", "2", "3"
-		);
-#endif /* CONFIG_64BIT */
-	
-	return time;
+	asm volatile(
+		"	.insn	rre,0xb2650000,2,0"
+		: "+d" (__fn), "=d" (__tmp), "=d" (__time));
+	return __time;
 }
 	
 /*
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 821dde8..809dd8d 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -534,19 +534,15 @@
  *
  * Returns: return code from CP's IUCV call
  */
-static __inline__ ulong
-b2f0(__u32 code, void *parm)
+static inline ulong b2f0(__u32 code, void *parm)
 {
+	register unsigned long reg0 asm ("0");
+	register unsigned long reg1 asm ("1");
 	iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
 
-	asm volatile (
-		"LRA   1,0(%1)\n\t"
-		"LR    0,%0\n\t"
-		".long 0xb2f01000"
-		:
-		: "d" (code), "a" (parm)
-		: "0", "1"
-		);
+	reg0 = code;
+	reg1 = virt_to_phys(parm);
+	asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
 
 	iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
 
@@ -1248,6 +1244,8 @@
 static int
 iucv_query_generic(int want_maxconn)
 {
+	register unsigned long reg0 asm ("0");
+	register unsigned long reg1 asm ("1");
 	iparml_purge *parm = (iparml_purge *)grab_param();
 	int bufsize, maxconn;
 	int ccode;
@@ -1256,18 +1254,15 @@
 	 * Call b2f0 and store R0 (max buffer size),
 	 * R1 (max connections) and CC.
 	 */
-	asm volatile (
-		"LRA   1,0(%4)\n\t"
-		"LR    0,%3\n\t"
-		".long 0xb2f01000\n\t"
-		"IPM   %0\n\t"
-		"SRL   %0,28\n\t"
-		"ST    0,%1\n\t"
-		"ST    1,%2\n\t"
-		: "=d" (ccode), "=m" (bufsize), "=m" (maxconn)
-		: "d" (QUERY), "a" (parm)
-		: "0", "1", "cc"
-		);
+	reg0 = QUERY;
+	reg1 = virt_to_phys(parm);
+	asm volatile(
+		"	.long	0xb2f01000\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		: "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
+	bufsize = reg0;
+	maxconn = reg1;
 	release_param(parm);
 
 	if (ccode)
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 5613b45..8364d54 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -8067,7 +8067,7 @@
 	neigh->parms = neigh_parms_clone(parms);
 	rcu_read_unlock();
 
-	neigh->type = inet_addr_type(*(u32 *) neigh->primary_key);
+	neigh->type = inet_addr_type(*(__be32 *) neigh->primary_key);
 	neigh->nud_state = NUD_NOARP;
 	neigh->ops = arp_direct_ops;
 	neigh->output = neigh->ops->queue_xmit;
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index a914129..479364d 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -253,11 +253,12 @@
 		kill_task = 1;
 
 #ifndef CONFIG_64BIT
-	asm volatile("ld 0,0(%0)\n"
-		     "ld 2,8(%0)\n"
-		     "ld 4,16(%0)\n"
-		     "ld 6,24(%0)"
-		     : : "a" (&S390_lowcore.floating_pt_save_area));
+	asm volatile(
+		"	ld	0,0(%0)\n"
+		"	ld	2,8(%0)\n"
+		"	ld	4,16(%0)\n"
+		"	ld	6,24(%0)"
+		: : "a" (&S390_lowcore.floating_pt_save_area));
 #endif
 
 	if (MACHINE_HAS_IEEE) {
@@ -274,37 +275,36 @@
 			 * Floating point control register can't be restored.
 			 * Task will be terminated.
 			 */
-			asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
+			asm volatile("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
 			kill_task = 1;
 
-		}
-		else
-			asm volatile (
-				"lfpc 0(%0)"
-				: : "a" (fpt_creg_save_area));
+		} else
+			asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area));
 
-		asm volatile("ld  0,0(%0)\n"
-			     "ld  1,8(%0)\n"
-			     "ld  2,16(%0)\n"
-			     "ld  3,24(%0)\n"
-			     "ld  4,32(%0)\n"
-			     "ld  5,40(%0)\n"
-			     "ld  6,48(%0)\n"
-			     "ld  7,56(%0)\n"
-			     "ld  8,64(%0)\n"
-			     "ld  9,72(%0)\n"
-			     "ld 10,80(%0)\n"
-			     "ld 11,88(%0)\n"
-			     "ld 12,96(%0)\n"
-			     "ld 13,104(%0)\n"
-			     "ld 14,112(%0)\n"
-			     "ld 15,120(%0)\n"
-			     : : "a" (fpt_save_area));
+		asm volatile(
+			"	ld	0,0(%0)\n"
+			"	ld	1,8(%0)\n"
+			"	ld	2,16(%0)\n"
+			"	ld	3,24(%0)\n"
+			"	ld	4,32(%0)\n"
+			"	ld	5,40(%0)\n"
+			"	ld	6,48(%0)\n"
+			"	ld	7,56(%0)\n"
+			"	ld	8,64(%0)\n"
+			"	ld	9,72(%0)\n"
+			"	ld	10,80(%0)\n"
+			"	ld	11,88(%0)\n"
+			"	ld	12,96(%0)\n"
+			"	ld	13,104(%0)\n"
+			"	ld	14,112(%0)\n"
+			"	ld	15,120(%0)\n"
+			: : "a" (fpt_save_area));
 	}
 
 	/* Revalidate access registers */
-	asm volatile("lam 0,15,0(%0)"
-		     : : "a" (&S390_lowcore.access_regs_save_area));
+	asm volatile(
+		"	lam	0,15,0(%0)"
+		: : "a" (&S390_lowcore.access_regs_save_area));
 	if (!mci->ar)
 		/*
 		 * Access registers have unknown contents.
@@ -321,11 +321,13 @@
 		s390_handle_damage("invalid control registers.");
 	else
 #ifdef CONFIG_64BIT
-		asm volatile("lctlg 0,15,0(%0)"
-			     : : "a" (&S390_lowcore.cregs_save_area));
+		asm volatile(
+			"	lctlg	0,15,0(%0)"
+			: : "a" (&S390_lowcore.cregs_save_area));
 #else
-		asm volatile("lctl 0,15,0(%0)"
-			     : : "a" (&S390_lowcore.cregs_save_area));
+		asm volatile(
+			"	lctl	0,15,0(%0)"
+			: : "a" (&S390_lowcore.cregs_save_area));
 #endif
 
 	/*
@@ -339,20 +341,23 @@
 	 * old contents (should be zero) otherwise set it to zero.
 	 */
 	if (!mci->pr)
-		asm volatile("sr 0,0\n"
-			     "sckpf"
-			     : : : "0", "cc");
+		asm volatile(
+			"	sr	0,0\n"
+			"	sckpf"
+			: : : "0", "cc");
 	else
 		asm volatile(
-			"l 0,0(%0)\n"
-			"sckpf"
-			: : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc");
+			"	l	0,0(%0)\n"
+			"	sckpf"
+			: : "a" (&S390_lowcore.tod_progreg_save_area)
+			: "0", "cc");
 #endif
 
 	/* Revalidate clock comparator register */
-	asm volatile ("stck 0(%1)\n"
-		      "sckc 0(%1)"
-		      : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
+	asm volatile(
+		"	stck	0(%1)\n"
+		"	sckc	0(%1)"
+		: "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
 
 	/* Check if old PSW is valid */
 	if (!mci->wp)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 261eaa4..d926272 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -295,7 +295,7 @@
 	  Even if you say Y here, the currently visible framebuffer console
 	  (/dev/tty0) will still be used as the system console by default, but
 	  you can alter that using a kernel command line option such as
-	  "console=ttyAM0". (Try "man bootparam" or see the documentation of
+	  "console=ttyAMA0". (Try "man bootparam" or see the documentation of
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
index 54c6b2a..bf4bf10 100644
--- a/drivers/serial/at91_serial.c
+++ b/drivers/serial/at91_serial.c
@@ -139,7 +139,7 @@
 		 * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21.
 		 *  We need to drive the pin manually.
 		 */
-		if (port->mapbase == AT91_BASE_US0) {
+		if (port->mapbase == AT91RM9200_BASE_US0) {
 			if (mctrl & TIOCM_RTS)
 				at91_set_gpio_value(AT91_PIN_PA21, 0);
 			else
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 0050431..f9b1719 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -25,6 +25,7 @@
 	default y if PXA27x
 	default y if ARCH_EP93XX
 	default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
+	default y if ARCH_PNX4008
 	# PPC:
 	default y if STB03xxx
 	default y if PPC_MPC52xx
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 4710eb0..97d57cf 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -14,6 +14,7 @@
 obj-$(CONFIG_USB_OHCI_HCD)	+= host/
 obj-$(CONFIG_USB_UHCI_HCD)	+= host/
 obj-$(CONFIG_USB_SL811_HCD)	+= host/
+obj-$(CONFIG_USB_U132_HCD)	+= host/
 obj-$(CONFIG_ETRAX_USB_HOST)	+= host/
 obj-$(CONFIG_USB_OHCI_AT91)	+= host/
 
@@ -23,6 +24,7 @@
 obj-$(CONFIG_USB_STORAGE)	+= storage/
 obj-$(CONFIG_USB)		+= storage/
 
+obj-$(CONFIG_USB_ACECAD)	+= input/
 obj-$(CONFIG_USB_AIPTEK)	+= input/
 obj-$(CONFIG_USB_ATI_REMOTE)	+= input/
 obj-$(CONFIG_USB_HID)		+= input/
@@ -31,8 +33,8 @@
 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_ACECAD)	+= input/
 obj-$(CONFIG_USB_XPAD)		+= input/
 
 obj-$(CONFIG_USB_CATC)		+= net/
@@ -47,22 +49,24 @@
 
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
+obj-$(CONFIG_USB_ADUTUX)	+= misc/
+obj-$(CONFIG_USB_APPLEDISPLAY)	+= misc/
 obj-$(CONFIG_USB_AUERSWALD)	+= misc/
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
 obj-$(CONFIG_USB_CYTHERM)	+= misc/
 obj-$(CONFIG_USB_EMI26)		+= misc/
 obj-$(CONFIG_USB_EMI62)		+= misc/
+obj-$(CONFIG_USB_FTDI_ELAN)	+= misc/
 obj-$(CONFIG_USB_IDMOUSE)	+= misc/
 obj-$(CONFIG_USB_LCD)		+= misc/
 obj-$(CONFIG_USB_LD)		+= misc/
 obj-$(CONFIG_USB_LED)		+= misc/
 obj-$(CONFIG_USB_LEGOTOWER)	+= misc/
+obj-$(CONFIG_USB_PHIDGETSERVO)	+= misc/
 obj-$(CONFIG_USB_RIO500)	+= misc/
+obj-$(CONFIG_USB_SISUSBVGA)	+= misc/
 obj-$(CONFIG_USB_TEST)		+= misc/
 obj-$(CONFIG_USB_USS720)	+= misc/
-obj-$(CONFIG_USB_PHIDGETSERVO)	+= misc/
-obj-$(CONFIG_USB_SISUSBVGA)	+= misc/
-obj-$(CONFIG_USB_APPLEDISPLAY)	+= misc/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= atm/
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index b38990a..465961a26 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -1621,26 +1621,32 @@
 	return ret;
 }
 
-static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+static struct attribute *attrs[] = {
+	&dev_attr_stat_status.attr,
+	&dev_attr_stat_mflags.attr,
+	&dev_attr_stat_human_status.attr,
+	&dev_attr_stat_delin.attr,
+	&dev_attr_stat_vidcpe.attr,
+	&dev_attr_stat_usrate.attr,
+	&dev_attr_stat_dsrate.attr,
+	&dev_attr_stat_usattenuation.attr,
+	&dev_attr_stat_dsattenuation.attr,
+	&dev_attr_stat_usmargin.attr,
+	&dev_attr_stat_dsmargin.attr,
+	&dev_attr_stat_txflow.attr,
+	&dev_attr_stat_rxflow.attr,
+	&dev_attr_stat_uscorr.attr,
+	&dev_attr_stat_dscorr.attr,
+	&dev_attr_stat_usunc.attr,
+	&dev_attr_stat_dsunc.attr,
+};
+static struct attribute_group attr_grp = {
+	.attrs = attrs,
+};
+
+static int create_fs_entries(struct usb_interface *intf)
 {
-	/* sysfs interface */
-	device_create_file(&intf->dev, &dev_attr_stat_status);
-	device_create_file(&intf->dev, &dev_attr_stat_mflags);
-	device_create_file(&intf->dev, &dev_attr_stat_human_status);
-	device_create_file(&intf->dev, &dev_attr_stat_delin);
-	device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
-	device_create_file(&intf->dev, &dev_attr_stat_usrate);
-	device_create_file(&intf->dev, &dev_attr_stat_dsrate);
-	device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
-	device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
-	device_create_file(&intf->dev, &dev_attr_stat_usmargin);
-	device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
-	device_create_file(&intf->dev, &dev_attr_stat_txflow);
-	device_create_file(&intf->dev, &dev_attr_stat_rxflow);
-	device_create_file(&intf->dev, &dev_attr_stat_uscorr);
-	device_create_file(&intf->dev, &dev_attr_stat_dscorr);
-	device_create_file(&intf->dev, &dev_attr_stat_usunc);
-	device_create_file(&intf->dev, &dev_attr_stat_dsunc);
+	return sysfs_create_group(&intf->dev.kobj, &attr_grp);
 }
 
 static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
@@ -1708,37 +1714,25 @@
 		return ret;
 	}
 
-	create_fs_entries(sc, intf);
+	ret = create_fs_entries(intf);
+	if (ret) {
+		uea_stop(sc);
+		kfree(sc);
+		return ret;
+	}
 	return 0;
 }
 
-static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+static void destroy_fs_entries(struct usb_interface *intf)
 {
-	/* sysfs interface */
-	device_remove_file(&intf->dev, &dev_attr_stat_status);
-	device_remove_file(&intf->dev, &dev_attr_stat_mflags);
-	device_remove_file(&intf->dev, &dev_attr_stat_human_status);
-	device_remove_file(&intf->dev, &dev_attr_stat_delin);
-	device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
-	device_remove_file(&intf->dev, &dev_attr_stat_usrate);
-	device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
-	device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
-	device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
-	device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
-	device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
-	device_remove_file(&intf->dev, &dev_attr_stat_txflow);
-	device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
-	device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
-	device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
-	device_remove_file(&intf->dev, &dev_attr_stat_usunc);
-	device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
+	sysfs_remove_group(&intf->dev.kobj, &attr_grp);
 }
 
 static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
 {
 	struct uea_softc *sc = usbatm->driver_data;
 
-	destroy_fs_entries(sc, intf);
+	destroy_fs_entries(intf);
 	uea_stop(sc);
 	kfree(sc);
 }
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 48dee4b8..9cac11c 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -813,7 +813,7 @@
 	return 0;
 }
 
-static struct file_operations usblp_fops = {
+static const struct file_operations usblp_fops = {
 	.owner =	THIS_MODULE,
 	.read =		usblp_read,
 	.write =	usblp_write,
@@ -927,7 +927,9 @@
 
 	/* Retrieve and store the device ID string. */
 	usblp_cache_device_id_string(usblp);
-	device_create_file(&intf->dev, &dev_attr_ieee1284_id);
+	retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id);
+	if (retval)
+		goto abort_intfdata;
 
 #ifdef DEBUG
 	usblp_check_status(usblp, 0);
@@ -1021,18 +1023,13 @@
 		for (e = 0; e < ifd->desc.bNumEndpoints; e++) {
 			epd = &ifd->endpoint[e].desc;
 
-			if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
-			    USB_ENDPOINT_XFER_BULK)
-				continue;
-
-			if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
+			if (usb_endpoint_is_bulk_out(epd))
 				if (!epwrite)
 					epwrite = epd;
 
-			} else {
+			if (usb_endpoint_is_bulk_in(epd))
 				if (!epread)
 					epread = epd;
-			}
 		}
 
 		/* Ignore buggy hardware without the right endpoints. */
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index ec51092..34e9bac 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -4,7 +4,7 @@
 
 usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
 			config.o file.o buffer.o sysfs.o endpoint.o \
-			devio.o notify.o
+			devio.o notify.o generic.o
 
 ifeq ($(CONFIG_PCI),y)
 	usbcore-objs	+= hcd-pci.o
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index f4f4ef0..840442a 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -104,7 +104,7 @@
 	dma_addr_t		*dma
 )
 {
-	struct usb_hcd		*hcd = bus->hcpriv;
+	struct usb_hcd		*hcd = bus_to_hcd(bus);
 	int 			i;
 
 	/* some USB hosts just use PIO */
@@ -127,7 +127,7 @@
 	dma_addr_t		dma
 )
 {
-	struct usb_hcd		*hcd = bus->hcpriv;
+	struct usb_hcd		*hcd = bus_to_hcd(bus);
 	int 			i;
 
 	if (!addr)
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 4c9e63e..bfb3731 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -475,7 +475,9 @@
 		if (result < 0) {
 			dev_err(ddev, "unable to read config index %d "
 			    "descriptor/%s\n", cfgno, "start");
-			goto err;
+			dev_err(ddev, "chopping to %d config(s)\n", cfgno);
+			dev->descriptor.bNumConfigurations = cfgno;
+			break;
 		} else if (result < 4) {
 			dev_err(ddev, "config index %d descriptor too short "
 			    "(expected %i, got %i)\n", cfgno,
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index c0f3734..3538c2f 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -593,7 +593,7 @@
 /* Kernel lock for "lastev" protection */
 static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
 {
-	struct usb_device_status *st = (struct usb_device_status *)file->private_data;
+	struct usb_device_status *st = file->private_data;
 	unsigned int mask = 0;
 
 	lock_kernel();
@@ -603,7 +603,7 @@
 			unlock_kernel();
 			return POLLIN;
 		}
-		
+
 		/* we may have dropped BKL - need to check for having lost the race */
 		if (file->private_data) {
 			kfree(st);
@@ -667,7 +667,7 @@
 	return ret;
 }
 
-struct file_operations usbfs_devices_fops = {
+const struct file_operations usbfs_devices_fops = {
 	.llseek =	usb_device_lseek,
 	.read =		usb_device_read,
 	.poll =		usb_device_poll,
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 32e0300..a94c63b 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -59,6 +59,9 @@
 #define USB_DEVICE_MAX			USB_MAXBUS * 128
 static struct class *usb_device_class;
 
+/* Mutual exclusion for removal, open, and release */
+DEFINE_MUTEX(usbfs_mutex);
+
 struct async {
 	struct list_head asynclist;
 	struct dev_state *ps;
@@ -87,9 +90,10 @@
 
 #define	MAX_USBFS_BUFFER_SIZE	16384
 
-static inline int connected (struct usb_device *dev)
+static inline int connected (struct dev_state *ps)
 {
-	return dev->state != USB_STATE_NOTATTACHED;
+	return (!list_empty(&ps->list) &&
+			ps->dev->state != USB_STATE_NOTATTACHED);
 }
 
 static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
@@ -118,7 +122,7 @@
 
 static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-	struct dev_state *ps = (struct dev_state *)file->private_data;
+	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
 	ssize_t ret = 0;
 	unsigned len;
@@ -127,7 +131,7 @@
 
 	pos = *ppos;
 	usb_lock_device(dev);
-	if (!connected(dev)) {
+	if (!connected(ps)) {
 		ret = -ENODEV;
 		goto err;
 	} else if (pos < 0) {
@@ -301,7 +305,7 @@
 
 static void async_completed(struct urb *urb, struct pt_regs *regs)
 {
-        struct async *as = (struct async *)urb->context;
+        struct async *as = urb->context;
         struct dev_state *ps = as->ps;
 	struct siginfo sinfo;
 
@@ -541,25 +545,25 @@
 	struct dev_state *ps;
 	int ret;
 
-	/* 
-	 * no locking necessary here, as chrdev_open has the kernel lock
-	 * (still acquire the kernel lock for safety)
-	 */
+	/* Protect against simultaneous removal or release */
+	mutex_lock(&usbfs_mutex);
+
 	ret = -ENOMEM;
 	if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
-		goto out_nolock;
+		goto out;
 
-	lock_kernel();
 	ret = -ENOENT;
 	/* check if we are called from a real node or usbfs */
 	if (imajor(inode) == USB_DEVICE_MAJOR)
 		dev = usbdev_lookup_minor(iminor(inode));
 	if (!dev)
 		dev = inode->i_private;
-	if (!dev) {
-		kfree(ps);
+	if (!dev)
 		goto out;
-	}
+	ret = usb_autoresume_device(dev, 1);
+	if (ret)
+		goto out;
+
 	usb_get_dev(dev);
 	ret = 0;
 	ps->dev = dev;
@@ -579,30 +583,36 @@
 	list_add_tail(&ps->list, &dev->filelist);
 	file->private_data = ps;
  out:
-	unlock_kernel();
- out_nolock:
-        return ret;
+	if (ret)
+		kfree(ps);
+	mutex_unlock(&usbfs_mutex);
+	return ret;
 }
 
 static int usbdev_release(struct inode *inode, struct file *file)
 {
-	struct dev_state *ps = (struct dev_state *)file->private_data;
+	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
 	unsigned int ifnum;
 
 	usb_lock_device(dev);
+
+	/* Protect against simultaneous open */
+	mutex_lock(&usbfs_mutex);
 	list_del_init(&ps->list);
+	mutex_unlock(&usbfs_mutex);
+
 	for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
 			ifnum++) {
 		if (test_bit(ifnum, &ps->ifclaimed))
 			releaseintf(ps, ifnum);
 	}
 	destroy_all_async(ps);
+	usb_autosuspend_device(dev, 1);
 	usb_unlock_device(dev);
 	usb_put_dev(dev);
-	ps->dev = NULL;
 	kfree(ps);
-        return 0;
+	return 0;
 }
 
 static int proc_control(struct dev_state *ps, void __user *arg)
@@ -1322,7 +1332,7 @@
 		}
 	}
 
-	if (!connected(ps->dev)) {
+	if (!connected(ps)) {
 		kfree(buf);
 		return -ENODEV;
 	}
@@ -1349,7 +1359,7 @@
 	/* let kernel drivers try to (re)bind to the interface */
 	case USBDEVFS_CONNECT:
 		usb_unlock_device(ps->dev);
-		bus_rescan_devices(intf->dev.bus);
+		retval = bus_rescan_devices(intf->dev.bus);
 		usb_lock_device(ps->dev);
 		break;
 
@@ -1413,7 +1423,7 @@
  */
 static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct dev_state *ps = (struct dev_state *)file->private_data;
+	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
 	void __user *p = (void __user *)arg;
 	int ret = -ENOTTY;
@@ -1421,7 +1431,7 @@
 	if (!(file->f_mode & FMODE_WRITE))
 		return -EPERM;
 	usb_lock_device(dev);
-	if (!connected(dev)) {
+	if (!connected(ps)) {
 		usb_unlock_device(dev);
 		return -ENODEV;
 	}
@@ -1556,18 +1566,18 @@
 /* No kernel lock - fine */
 static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
 {
-	struct dev_state *ps = (struct dev_state *)file->private_data;
-        unsigned int mask = 0;
+	struct dev_state *ps = file->private_data;
+	unsigned int mask = 0;
 
 	poll_wait(file, &ps->wait, wait);
 	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
 		mask |= POLLOUT | POLLWRNORM;
-	if (!connected(ps->dev))
+	if (!connected(ps))
 		mask |= POLLERR | POLLHUP;
 	return mask;
 }
 
-struct file_operations usbfs_device_file_operations = {
+const struct file_operations usbfs_device_file_operations = {
 	.llseek =	usbdev_lseek,
 	.read =		usbdev_read,
 	.poll =		usbdev_poll,
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index ec89065..113e484 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -17,12 +17,14 @@
  *
  * NOTE! This is not actually a driver at all, rather this is
  * just a collection of helper routines that implement the
- * generic USB things that the real drivers can use..
+ * matching, probing, releasing, suspending and resuming for
+ * real drivers.
  *
  */
 
 #include <linux/device.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 #include "hcd.h"
 #include "usb.h"
 
@@ -34,38 +36,6 @@
 	struct usb_device_id id;
 };
 
-
-static int generic_probe(struct device *dev)
-{
-	return 0;
-}
-static int generic_remove(struct device *dev)
-{
-	struct usb_device *udev = to_usb_device(dev);
-
-	/* if this is only an unbind, not a physical disconnect, then
-	 * unconfigure the device */
-	if (udev->state == USB_STATE_CONFIGURED)
-		usb_set_configuration(udev, 0);
-
-	/* in case the call failed or the device was suspended */
-	if (udev->state >= USB_STATE_CONFIGURED)
-		usb_disable_device(udev, 0);
-	return 0;
-}
-
-struct device_driver usb_generic_driver = {
-	.owner = THIS_MODULE,
-	.name =	"usb",
-	.bus = &usb_bus_type,
-	.probe = generic_probe,
-	.remove = generic_remove,
-};
-
-/* Fun hack to determine if the struct device is a
- * usb device or a usb interface. */
-int usb_generic_driver_data;
-
 #ifdef CONFIG_HOTPLUG
 
 /*
@@ -80,6 +50,7 @@
 	u32 idVendor = 0;
 	u32 idProduct = 0;
 	int fields = 0;
+	int retval = 0;
 
 	fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
 	if (fields < 2)
@@ -99,10 +70,12 @@
 	spin_unlock(&usb_drv->dynids.lock);
 
 	if (get_driver(driver)) {
-		driver_attach(driver);
+		retval = driver_attach(driver);
 		put_driver(driver);
 	}
 
+	if (retval)
+		return retval;
 	return count;
 }
 static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
@@ -115,7 +88,7 @@
 		goto exit;
 
 	if (usb_drv->probe != NULL)
-		error = sysfs_create_file(&usb_drv->driver.kobj,
+		error = sysfs_create_file(&usb_drv->drvwrap.driver.kobj,
 					  &driver_attr_new_id.attr);
 exit:
 	return error;
@@ -127,7 +100,7 @@
 		return;
 
 	if (usb_drv->probe != NULL)
-		sysfs_remove_file(&usb_drv->driver.kobj,
+		sysfs_remove_file(&usb_drv->drvwrap.driver.kobj,
 				  &driver_attr_new_id.attr);
 }
 
@@ -174,21 +147,57 @@
 }
 
 
-/* called from driver core with usb_bus_type.subsys writelock */
+/* called from driver core with dev locked */
+static int usb_probe_device(struct device *dev)
+{
+	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+	struct usb_device *udev;
+	int error = -ENODEV;
+
+	dev_dbg(dev, "%s\n", __FUNCTION__);
+
+	if (!is_usb_device(dev))	/* Sanity check */
+		return error;
+
+	udev = to_usb_device(dev);
+
+	/* TODO: Add real matching code */
+
+	/* The device should always appear to be in use
+	 * unless the driver suports autosuspend.
+	 */
+	udev->pm_usage_cnt = !(udriver->supports_autosuspend);
+
+	error = udriver->probe(udev);
+	return error;
+}
+
+/* called from driver core with dev locked */
+static int usb_unbind_device(struct device *dev)
+{
+	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+
+	udriver->disconnect(to_usb_device(dev));
+	return 0;
+}
+
+
+/* called from driver core with dev locked */
 static int usb_probe_interface(struct device *dev)
 {
-	struct usb_interface * intf = to_usb_interface(dev);
-	struct usb_driver * driver = to_usb_driver(dev->driver);
+	struct usb_driver *driver = to_usb_driver(dev->driver);
+	struct usb_interface *intf;
+	struct usb_device *udev;
 	const struct usb_device_id *id;
 	int error = -ENODEV;
 
 	dev_dbg(dev, "%s\n", __FUNCTION__);
 
-	if (!driver->probe)
+	if (is_usb_device(dev))		/* Sanity check */
 		return error;
-	/* FIXME we'd much prefer to just resume it ... */
-	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
-		return -EHOSTUNREACH;
+
+	intf = to_usb_interface(dev);
+	udev = interface_to_usbdev(intf);
 
 	id = usb_match_id(intf, driver->id_table);
 	if (!id)
@@ -196,48 +205,165 @@
 	if (id) {
 		dev_dbg(dev, "%s - got id\n", __FUNCTION__);
 
+		error = usb_autoresume_device(udev, 1);
+		if (error)
+			return error;
+
 		/* Interface "power state" doesn't correspond to any hardware
 		 * state whatsoever.  We use it to record when it's bound to
 		 * a driver that may start I/0:  it's not frozen/quiesced.
 		 */
 		mark_active(intf);
 		intf->condition = USB_INTERFACE_BINDING;
+
+		/* The interface should always appear to be in use
+		 * unless the driver suports autosuspend.
+		 */
+		intf->pm_usage_cnt = !(driver->supports_autosuspend);
+
 		error = driver->probe(intf, id);
 		if (error) {
 			mark_quiesced(intf);
+			intf->needs_remote_wakeup = 0;
 			intf->condition = USB_INTERFACE_UNBOUND;
 		} else
 			intf->condition = USB_INTERFACE_BOUND;
+
+		usb_autosuspend_device(udev, 1);
 	}
 
 	return error;
 }
 
-/* called from driver core with usb_bus_type.subsys writelock */
+/* called from driver core with dev locked */
 static int usb_unbind_interface(struct device *dev)
 {
+	struct usb_driver *driver = to_usb_driver(dev->driver);
 	struct usb_interface *intf = to_usb_interface(dev);
-	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+	struct usb_device *udev;
+	int error;
 
 	intf->condition = USB_INTERFACE_UNBINDING;
 
+	/* Autoresume for set_interface call below */
+	udev = interface_to_usbdev(intf);
+	error = usb_autoresume_device(udev, 1);
+
 	/* release all urbs for this interface */
 	usb_disable_interface(interface_to_usbdev(intf), intf);
 
-	if (driver && driver->disconnect)
-		driver->disconnect(intf);
+	driver->disconnect(intf);
 
 	/* reset other interface state */
 	usb_set_interface(interface_to_usbdev(intf),
 			intf->altsetting[0].desc.bInterfaceNumber,
 			0);
 	usb_set_intfdata(intf, NULL);
+
 	intf->condition = USB_INTERFACE_UNBOUND;
 	mark_quiesced(intf);
+	intf->needs_remote_wakeup = 0;
+
+	if (!error)
+		usb_autosuspend_device(udev, 1);
 
 	return 0;
 }
 
+/**
+ * usb_driver_claim_interface - bind a driver to an interface
+ * @driver: the driver to be bound
+ * @iface: the interface to which it will be bound; must be in the
+ *	usb device's active configuration
+ * @priv: driver data associated with that interface
+ *
+ * This is used by usb device drivers that need to claim more than one
+ * interface on a device when probing (audio and acm are current examples).
+ * No device driver should directly modify internal usb_interface or
+ * usb_device structure members.
+ *
+ * Few drivers should need to use this routine, since the most natural
+ * way to bind to an interface is to return the private data from
+ * the driver's probe() method.
+ *
+ * Callers must own the device lock and the driver model's usb_bus_type.subsys
+ * writelock.  So driver probe() entries don't need extra locking,
+ * but other call contexts may need to explicitly claim those locks.
+ */
+int usb_driver_claim_interface(struct usb_driver *driver,
+				struct usb_interface *iface, void* priv)
+{
+	struct device *dev = &iface->dev;
+	struct usb_device *udev = interface_to_usbdev(iface);
+	int retval = 0;
+
+	if (dev->driver)
+		return -EBUSY;
+
+	dev->driver = &driver->drvwrap.driver;
+	usb_set_intfdata(iface, priv);
+
+	usb_pm_lock(udev);
+	iface->condition = USB_INTERFACE_BOUND;
+	mark_active(iface);
+	iface->pm_usage_cnt = !(driver->supports_autosuspend);
+	usb_pm_unlock(udev);
+
+	/* if interface was already added, bind now; else let
+	 * the future device_add() bind it, bypassing probe()
+	 */
+	if (device_is_registered(dev))
+		retval = device_bind_driver(dev);
+
+	return retval;
+}
+EXPORT_SYMBOL(usb_driver_claim_interface);
+
+/**
+ * usb_driver_release_interface - unbind a driver from an interface
+ * @driver: the driver to be unbound
+ * @iface: the interface from which it will be unbound
+ *
+ * This can be used by drivers to release an interface without waiting
+ * for their disconnect() methods to be called.  In typical cases this
+ * also causes the driver disconnect() method to be called.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ * Callers must own the device lock and the driver model's usb_bus_type.subsys
+ * writelock.  So driver disconnect() entries don't need extra locking,
+ * but other call contexts may need to explicitly claim those locks.
+ */
+void usb_driver_release_interface(struct usb_driver *driver,
+					struct usb_interface *iface)
+{
+	struct device *dev = &iface->dev;
+	struct usb_device *udev = interface_to_usbdev(iface);
+
+	/* this should never happen, don't release something that's not ours */
+	if (!dev->driver || dev->driver != &driver->drvwrap.driver)
+		return;
+
+	/* don't release from within disconnect() */
+	if (iface->condition != USB_INTERFACE_BOUND)
+		return;
+
+	/* don't release if the interface hasn't been added yet */
+	if (device_is_registered(dev)) {
+		iface->condition = USB_INTERFACE_UNBINDING;
+		device_release_driver(dev);
+	}
+
+	dev->driver = NULL;
+	usb_set_intfdata(iface, NULL);
+
+	usb_pm_lock(udev);
+	iface->condition = USB_INTERFACE_UNBOUND;
+	mark_quiesced(iface);
+	iface->needs_remote_wakeup = 0;
+	usb_pm_unlock(udev);
+}
+EXPORT_SYMBOL(usb_driver_release_interface);
+
 /* returns 0 if no match, 1 if match */
 static int usb_match_one_id(struct usb_interface *interface,
 			    const struct usb_device_id *id)
@@ -381,35 +507,223 @@
 
 int usb_device_match(struct device *dev, struct device_driver *drv)
 {
-	struct usb_interface *intf;
-	struct usb_driver *usb_drv;
-	const struct usb_device_id *id;
+	/* devices and interfaces are handled separately */
+	if (is_usb_device(dev)) {
 
-	/* check for generic driver, which we don't match any device with */
-	if (drv == &usb_generic_driver)
-		return 0;
+		/* interface drivers never match devices */
+		if (!is_usb_device_driver(drv))
+			return 0;
 
-	intf = to_usb_interface(dev);
-	usb_drv = to_usb_driver(drv);
-
-	id = usb_match_id(intf, usb_drv->id_table);
-	if (id)
+		/* TODO: Add real matching code */
 		return 1;
 
-	id = usb_match_dynamic_id(intf, usb_drv);
-	if (id)
-		return 1;
+	} else {
+		struct usb_interface *intf;
+		struct usb_driver *usb_drv;
+		const struct usb_device_id *id;
+
+		/* device drivers never match interfaces */
+		if (is_usb_device_driver(drv))
+			return 0;
+
+		intf = to_usb_interface(dev);
+		usb_drv = to_usb_driver(drv);
+
+		id = usb_match_id(intf, usb_drv->id_table);
+		if (id)
+			return 1;
+
+		id = usb_match_dynamic_id(intf, usb_drv);
+		if (id)
+			return 1;
+	}
+
 	return 0;
 }
 
+#ifdef	CONFIG_HOTPLUG
+
+/*
+ * This sends an uevent to userspace, typically helping to load driver
+ * or other modules, configure the device, and more.  Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ * We're called either from khubd (the typical case) or from root hub
+ * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
+ * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
+ * device (and this configuration!) are still present.
+ */
+static int usb_uevent(struct device *dev, char **envp, int num_envp,
+		      char *buffer, int buffer_size)
+{
+	struct usb_interface *intf;
+	struct usb_device *usb_dev;
+	struct usb_host_interface *alt;
+	int i = 0;
+	int length = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	/* driver is often null here; dev_dbg() would oops */
+	pr_debug ("usb %s: uevent\n", dev->bus_id);
+
+	if (is_usb_device(dev)) {
+		usb_dev = to_usb_device(dev);
+		alt = NULL;
+	} else {
+		intf = to_usb_interface(dev);
+		usb_dev = interface_to_usbdev(intf);
+		alt = intf->cur_altsetting;
+	}
+
+	if (usb_dev->devnum < 0) {
+		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+		return -ENODEV;
+	}
+	if (!usb_dev->bus) {
+		pr_debug ("usb %s: bus removed?\n", dev->bus_id);
+		return -ENODEV;
+	}
+
+#ifdef	CONFIG_USB_DEVICEFS
+	/* If this is available, userspace programs can directly read
+	 * all the device descriptors we don't tell them about.  Or
+	 * even act as usermode drivers.
+	 *
+	 * FIXME reduce hardwired intelligence here
+	 */
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "DEVICE=/proc/bus/usb/%03d/%03d",
+			   usb_dev->bus->busnum, usb_dev->devnum))
+		return -ENOMEM;
+#endif
+
+	/* per-device configurations are common */
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "PRODUCT=%x/%x/%x",
+			   le16_to_cpu(usb_dev->descriptor.idVendor),
+			   le16_to_cpu(usb_dev->descriptor.idProduct),
+			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+		return -ENOMEM;
+
+	/* class-based driver binding models */
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "TYPE=%d/%d/%d",
+			   usb_dev->descriptor.bDeviceClass,
+			   usb_dev->descriptor.bDeviceSubClass,
+			   usb_dev->descriptor.bDeviceProtocol))
+		return -ENOMEM;
+
+	if (!is_usb_device(dev)) {
+
+		if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "INTERFACE=%d/%d/%d",
+			   alt->desc.bInterfaceClass,
+			   alt->desc.bInterfaceSubClass,
+			   alt->desc.bInterfaceProtocol))
+			return -ENOMEM;
+
+		if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+			   le16_to_cpu(usb_dev->descriptor.idVendor),
+			   le16_to_cpu(usb_dev->descriptor.idProduct),
+			   le16_to_cpu(usb_dev->descriptor.bcdDevice),
+			   usb_dev->descriptor.bDeviceClass,
+			   usb_dev->descriptor.bDeviceSubClass,
+			   usb_dev->descriptor.bDeviceProtocol,
+			   alt->desc.bInterfaceClass,
+			   alt->desc.bInterfaceSubClass,
+			   alt->desc.bInterfaceProtocol))
+			return -ENOMEM;
+	}
+
+	envp[i] = NULL;
+
+	return 0;
+}
+
+#else
+
+static int usb_uevent(struct device *dev, char **envp,
+			int num_envp, char *buffer, int buffer_size)
+{
+	return -ENODEV;
+}
+
+#endif	/* CONFIG_HOTPLUG */
+
 /**
- * usb_register_driver - register a USB driver
- * @new_driver: USB operations for the driver
+ * usb_register_device_driver - register a USB device (not interface) driver
+ * @new_udriver: USB operations for the device driver
  * @owner: module owner of this driver.
  *
- * Registers a USB driver with the USB core.  The list of unattached
- * interfaces will be rescanned whenever a new driver is added, allowing
- * the new driver to attach to any recognized devices.
+ * Registers a USB device driver with the USB core.  The list of
+ * unattached devices will be rescanned whenever a new driver is
+ * added, allowing the new driver to attach to any recognized devices.
+ * Returns a negative error code on failure and 0 on success.
+ */
+int usb_register_device_driver(struct usb_device_driver *new_udriver,
+		struct module *owner)
+{
+	int retval = 0;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	new_udriver->drvwrap.for_devices = 1;
+	new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
+	new_udriver->drvwrap.driver.bus = &usb_bus_type;
+	new_udriver->drvwrap.driver.probe = usb_probe_device;
+	new_udriver->drvwrap.driver.remove = usb_unbind_device;
+	new_udriver->drvwrap.driver.owner = owner;
+
+	retval = driver_register(&new_udriver->drvwrap.driver);
+
+	if (!retval) {
+		pr_info("%s: registered new device driver %s\n",
+			usbcore_name, new_udriver->name);
+		usbfs_update_special();
+	} else {
+		printk(KERN_ERR "%s: error %d registering device "
+			"	driver %s\n",
+			usbcore_name, retval, new_udriver->name);
+	}
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(usb_register_device_driver);
+
+/**
+ * usb_deregister_device_driver - unregister a USB device (not interface) driver
+ * @udriver: USB operations of the device driver to unregister
+ * Context: must be able to sleep
+ *
+ * Unlinks the specified driver from the internal USB driver list.
+ */
+void usb_deregister_device_driver(struct usb_device_driver *udriver)
+{
+	pr_info("%s: deregistering device driver %s\n",
+			usbcore_name, udriver->name);
+
+	driver_unregister(&udriver->drvwrap.driver);
+	usbfs_update_special();
+}
+EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
+
+/**
+ * usb_register_driver - register a USB interface driver
+ * @new_driver: USB operations for the interface driver
+ * @owner: module owner of this driver.
+ *
+ * Registers a USB interface driver with the USB core.  The list of
+ * unattached interfaces will be rescanned whenever a new driver is
+ * added, allowing the new driver to attach to any recognized interfaces.
  * Returns a negative error code on failure and 0 on success.
  *
  * NOTE: if you want your driver to use the USB major number, you must call
@@ -423,23 +737,25 @@
 	if (usb_disabled())
 		return -ENODEV;
 
-	new_driver->driver.name = (char *)new_driver->name;
-	new_driver->driver.bus = &usb_bus_type;
-	new_driver->driver.probe = usb_probe_interface;
-	new_driver->driver.remove = usb_unbind_interface;
-	new_driver->driver.owner = owner;
+	new_driver->drvwrap.for_devices = 0;
+	new_driver->drvwrap.driver.name = (char *) new_driver->name;
+	new_driver->drvwrap.driver.bus = &usb_bus_type;
+	new_driver->drvwrap.driver.probe = usb_probe_interface;
+	new_driver->drvwrap.driver.remove = usb_unbind_interface;
+	new_driver->drvwrap.driver.owner = owner;
 	spin_lock_init(&new_driver->dynids.lock);
 	INIT_LIST_HEAD(&new_driver->dynids.list);
 
-	retval = driver_register(&new_driver->driver);
+	retval = driver_register(&new_driver->drvwrap.driver);
 
 	if (!retval) {
-		pr_info("%s: registered new driver %s\n",
+		pr_info("%s: registered new interface driver %s\n",
 			usbcore_name, new_driver->name);
 		usbfs_update_special();
 		usb_create_newid_file(new_driver);
 	} else {
-		printk(KERN_ERR "%s: error %d registering driver %s\n",
+		printk(KERN_ERR "%s: error %d registering interface "
+			"	driver %s\n",
 			usbcore_name, retval, new_driver->name);
 	}
 
@@ -448,8 +764,8 @@
 EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
 
 /**
- * usb_deregister - unregister a USB driver
- * @driver: USB operations of the driver to unregister
+ * usb_deregister - unregister a USB interface driver
+ * @driver: USB operations of the interface driver to unregister
  * Context: must be able to sleep
  *
  * Unlinks the specified driver from the internal USB driver list.
@@ -460,12 +776,554 @@
  */
 void usb_deregister(struct usb_driver *driver)
 {
-	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
+	pr_info("%s: deregistering interface driver %s\n",
+			usbcore_name, driver->name);
 
 	usb_remove_newid_file(driver);
 	usb_free_dynids(driver);
-	driver_unregister(&driver->driver);
+	driver_unregister(&driver->drvwrap.driver);
 
 	usbfs_update_special();
 }
 EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+
+#ifdef CONFIG_PM
+
+/* Caller has locked udev's pm_mutex */
+static int suspend_device(struct usb_device *udev, pm_message_t msg)
+{
+	struct usb_device_driver	*udriver;
+	int				status = 0;
+
+	if (udev->state == USB_STATE_NOTATTACHED ||
+			udev->state == USB_STATE_SUSPENDED)
+		goto done;
+
+	/* For devices that don't have a driver, we do a standard suspend. */
+	if (udev->dev.driver == NULL) {
+		udev->do_remote_wakeup = 0;
+		status = usb_port_suspend(udev);
+		goto done;
+	}
+
+	udriver = to_usb_device_driver(udev->dev.driver);
+	status = udriver->suspend(udev, msg);
+
+done:
+	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+	if (status == 0)
+		udev->dev.power.power_state.event = msg.event;
+	return status;
+}
+
+/* Caller has locked udev's pm_mutex */
+static int resume_device(struct usb_device *udev)
+{
+	struct usb_device_driver	*udriver;
+	int				status = 0;
+
+	if (udev->state == USB_STATE_NOTATTACHED ||
+			udev->state != USB_STATE_SUSPENDED)
+		goto done;
+
+	/* Can't resume it if it doesn't have a driver. */
+	if (udev->dev.driver == NULL) {
+		status = -ENOTCONN;
+		goto done;
+	}
+
+	udriver = to_usb_device_driver(udev->dev.driver);
+	status = udriver->resume(udev);
+
+done:
+	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+	if (status == 0)
+		udev->dev.power.power_state.event = PM_EVENT_ON;
+	return status;
+}
+
+/* Caller has locked intf's usb_device's pm mutex */
+static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+{
+	struct usb_driver	*driver;
+	int			status = 0;
+
+	/* with no hardware, USB interfaces only use FREEZE and ON states */
+	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+			!is_active(intf))
+		goto done;
+
+	if (intf->condition == USB_INTERFACE_UNBOUND)	/* This can't happen */
+		goto done;
+	driver = to_usb_driver(intf->dev.driver);
+
+	if (driver->suspend && driver->resume) {
+		status = driver->suspend(intf, msg);
+		if (status == 0)
+			mark_quiesced(intf);
+		else if (!interface_to_usbdev(intf)->auto_pm)
+			dev_err(&intf->dev, "%s error %d\n",
+					"suspend", status);
+	} else {
+		// FIXME else if there's no suspend method, disconnect...
+		// Not possible if auto_pm is set...
+		dev_warn(&intf->dev, "no suspend for driver %s?\n",
+				driver->name);
+		mark_quiesced(intf);
+	}
+
+done:
+	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+	if (status == 0)
+		intf->dev.power.power_state.event = msg.event;
+	return status;
+}
+
+/* Caller has locked intf's usb_device's pm_mutex */
+static int resume_interface(struct usb_interface *intf)
+{
+	struct usb_driver	*driver;
+	int			status = 0;
+
+	if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+			is_active(intf))
+		goto done;
+
+	/* Don't let autoresume interfere with unbinding */
+	if (intf->condition == USB_INTERFACE_UNBINDING)
+		goto done;
+
+	/* Can't resume it if it doesn't have a driver. */
+	if (intf->condition == USB_INTERFACE_UNBOUND) {
+		status = -ENOTCONN;
+		goto done;
+	}
+	driver = to_usb_driver(intf->dev.driver);
+
+	if (driver->resume) {
+		status = driver->resume(intf);
+		if (status)
+			dev_err(&intf->dev, "%s error %d\n",
+					"resume", status);
+		else
+			mark_active(intf);
+	} else {
+		dev_warn(&intf->dev, "no resume for driver %s?\n",
+				driver->name);
+		mark_active(intf);
+	}
+
+done:
+	// dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+	if (status == 0)
+		intf->dev.power.power_state.event = PM_EVENT_ON;
+	return status;
+}
+
+/**
+ * usb_suspend_both - suspend a USB device and its interfaces
+ * @udev: the usb_device to suspend
+ * @msg: Power Management message describing this state transition
+ *
+ * This is the central routine for suspending USB devices.  It calls the
+ * suspend methods for all the interface drivers in @udev and then calls
+ * the suspend method for @udev itself.  If an error occurs at any stage,
+ * all the interfaces which were suspended are resumed so that they remain
+ * in the same state as the device.
+ *
+ * If an autosuspend is in progress (@udev->auto_pm is set), the routine
+ * checks first to make sure that neither the device itself or any of its
+ * active interfaces is in use (pm_usage_cnt is greater than 0).  If they
+ * are, the autosuspend fails.
+ *
+ * If the suspend succeeds, the routine recursively queues an autosuspend
+ * request for @udev's parent device, thereby propagating the change up
+ * the device tree.  If all of the parent's children are now suspended,
+ * the parent will autosuspend in turn.
+ *
+ * The suspend method calls are subject to mutual exclusion under control
+ * of @udev's pm_mutex.  Many of these calls are also under the protection
+ * of @udev's device lock (including all requests originating outside the
+ * USB subsystem), but autosuspend requests generated by a child device or
+ * interface driver may not be.  Usbcore will insure that the method calls
+ * do not arrive during bind, unbind, or reset operations.  However, drivers
+ * must be prepared to handle suspend calls arriving at unpredictable times.
+ * The only way to block such calls is to do an autoresume (preventing
+ * autosuspends) while holding @udev's device lock (preventing outside
+ * suspends).
+ *
+ * The caller must hold @udev->pm_mutex.
+ *
+ * This routine can run only in process context.
+ */
+int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+{
+	int			status = 0;
+	int			i = 0;
+	struct usb_interface	*intf;
+	struct usb_device	*parent = udev->parent;
+
+	cancel_delayed_work(&udev->autosuspend);
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return 0;
+	if (udev->state == USB_STATE_SUSPENDED)
+		return 0;
+
+	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+
+	/* For autosuspend, fail fast if anything is in use.
+	 * Also fail if any interfaces require remote wakeup but it
+	 * isn't available. */
+	if (udev->auto_pm) {
+		if (udev->pm_usage_cnt > 0)
+			return -EBUSY;
+		if (udev->actconfig) {
+			for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+				intf = udev->actconfig->interface[i];
+				if (!is_active(intf))
+					continue;
+				if (intf->pm_usage_cnt > 0)
+					return -EBUSY;
+				if (intf->needs_remote_wakeup &&
+						!udev->do_remote_wakeup) {
+					dev_dbg(&udev->dev,
+	"remote wakeup needed for autosuspend\n");
+					return -EOPNOTSUPP;
+				}
+			}
+			i = 0;
+		}
+	}
+
+	/* Suspend all the interfaces and then udev itself */
+	if (udev->actconfig) {
+		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			intf = udev->actconfig->interface[i];
+			status = suspend_interface(intf, msg);
+			if (status != 0)
+				break;
+		}
+	}
+	if (status == 0)
+		status = suspend_device(udev, msg);
+
+	/* If the suspend failed, resume interfaces that did get suspended */
+	if (status != 0) {
+		while (--i >= 0) {
+			intf = udev->actconfig->interface[i];
+			resume_interface(intf);
+		}
+
+	/* If the suspend succeeded, propagate it up the tree */
+	} else if (parent)
+		usb_autosuspend_device(parent, 0);
+
+	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+	return status;
+}
+
+/**
+ * usb_resume_both - resume a USB device and its interfaces
+ * @udev: the usb_device to resume
+ *
+ * This is the central routine for resuming USB devices.  It calls the
+ * the resume method for @udev and then calls the resume methods for all
+ * the interface drivers in @udev.
+ *
+ * Before starting the resume, the routine calls itself recursively for
+ * the parent device of @udev, thereby propagating the change up the device
+ * tree and assuring that @udev will be able to resume.  If the parent is
+ * unable to resume successfully, the routine fails.
+ *
+ * The resume method calls are subject to mutual exclusion under control
+ * of @udev's pm_mutex.  Many of these calls are also under the protection
+ * of @udev's device lock (including all requests originating outside the
+ * USB subsystem), but autoresume requests generated by a child device or
+ * interface driver may not be.  Usbcore will insure that the method calls
+ * do not arrive during bind, unbind, or reset operations.  However, drivers
+ * must be prepared to handle resume calls arriving at unpredictable times.
+ * The only way to block such calls is to do an autoresume (preventing
+ * other autoresumes) while holding @udev's device lock (preventing outside
+ * resumes).
+ *
+ * The caller must hold @udev->pm_mutex.
+ *
+ * This routine can run only in process context.
+ */
+int usb_resume_both(struct usb_device *udev)
+{
+	int			status = 0;
+	int			i;
+	struct usb_interface	*intf;
+	struct usb_device	*parent = udev->parent;
+
+	cancel_delayed_work(&udev->autosuspend);
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
+
+	/* Propagate the resume up the tree, if necessary */
+	if (udev->state == USB_STATE_SUSPENDED) {
+		if (parent) {
+			usb_pm_lock(parent);
+			parent->auto_pm = 1;
+			status = usb_resume_both(parent);
+		} else {
+
+			/* We can't progagate beyond the USB subsystem,
+			 * so if a root hub's controller is suspended
+			 * then we're stuck. */
+			if (udev->dev.parent->power.power_state.event !=
+					PM_EVENT_ON)
+				status = -EHOSTUNREACH;
+		}
+		if (status == 0)
+			status = resume_device(udev);
+		if (parent)
+			usb_pm_unlock(parent);
+	} else {
+
+		/* Needed only for setting udev->dev.power.power_state.event
+		 * and for possible debugging message. */
+		status = resume_device(udev);
+	}
+
+	/* Now the parent won't suspend until we are finished */
+
+	if (status == 0 && udev->actconfig) {
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			intf = udev->actconfig->interface[i];
+			resume_interface(intf);
+		}
+	}
+
+	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+	return status;
+}
+
+#ifdef CONFIG_USB_SUSPEND
+
+/**
+ * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
+ * @udev: the usb_device to autosuspend
+ * @dec_usage_cnt: flag to decrement @udev's PM-usage counter
+ *
+ * This routine should be called when a core subsystem is finished using
+ * @udev and wants to allow it to autosuspend.  Examples would be when
+ * @udev's device file in usbfs is closed or after a configuration change.
+ *
+ * @dec_usage_cnt should be 1 if the subsystem previously incremented
+ * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
+ * otherwise it should be 0.
+ *
+ * If the usage counter for @udev or any of its active interfaces is greater
+ * than 0, the autosuspend request will not be queued.  (If an interface
+ * driver does not support autosuspend then its usage counter is permanently
+ * positive.)  Likewise, if an interface driver requires remote-wakeup
+ * capability during autosuspend but remote wakeup is disabled, the
+ * autosuspend will fail.
+ *
+ * Often the caller will hold @udev's device lock, but this is not
+ * necessary.
+ *
+ * This routine can run only in process context.
+ */
+void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+{
+	usb_pm_lock(udev);
+	udev->pm_usage_cnt -= dec_usage_cnt;
+	if (udev->pm_usage_cnt <= 0)
+		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+				USB_AUTOSUSPEND_DELAY);
+	usb_pm_unlock(udev);
+	// dev_dbg(&udev->dev, "%s: cnt %d\n",
+	//		__FUNCTION__, udev->pm_usage_cnt);
+}
+
+/**
+ * usb_autoresume_device - immediately autoresume a USB device and its interfaces
+ * @udev: the usb_device to autoresume
+ * @inc_usage_cnt: flag to increment @udev's PM-usage counter
+ *
+ * This routine should be called when a core subsystem wants to use @udev
+ * and needs to guarantee that it is not suspended.  In addition, the
+ * caller can prevent @udev from being autosuspended subsequently.  (Note
+ * that this will not prevent suspend events originating in the PM core.)
+ * Examples would be when @udev's device file in usbfs is opened (autosuspend
+ * should be prevented until the file is closed) or when a remote-wakeup
+ * request is received (later autosuspends should not be prevented).
+ *
+ * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
+ * autosuspends.  This prevention will persist until the usage counter is
+ * decremented again (such as by passing 1 to usb_autosuspend_device).
+ * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
+ * Regardless, if the autoresume fails then the usage counter is not
+ * incremented.
+ *
+ * Often the caller will hold @udev's device lock, but this is not
+ * necessary (and attempting it might cause deadlock).
+ *
+ * This routine can run only in process context.
+ */
+int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+{
+	int	status;
+
+	usb_pm_lock(udev);
+	udev->pm_usage_cnt += inc_usage_cnt;
+	udev->auto_pm = 1;
+	status = usb_resume_both(udev);
+	if (status != 0)
+		udev->pm_usage_cnt -= inc_usage_cnt;
+	usb_pm_unlock(udev);
+	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
+	//		__FUNCTION__, status, udev->pm_usage_cnt);
+	return status;
+}
+
+/**
+ * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
+ * @intf: the usb_interface whose counter should be decremented
+ *
+ * This routine should be called by an interface driver when it is
+ * finished using @intf and wants to allow it to autosuspend.  A typical
+ * example would be a character-device driver when its device file is
+ * closed.
+ *
+ * The routine decrements @intf's usage counter.  When the counter reaches
+ * 0, a delayed autosuspend request for @intf's device is queued.  When
+ * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all
+ * the other usage counters for the sibling interfaces and @intf's
+ * usb_device, the device and all its interfaces will be autosuspended.
+ *
+ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+ * core will not change its value other than the increment and decrement
+ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+ * may use this simple counter-oriented discipline or may set the value
+ * any way it likes.
+ *
+ * If the driver has set @intf->needs_remote_wakeup then autosuspend will
+ * take place only if the device's remote-wakeup facility is enabled.
+ *
+ * Suspend method calls queued by this routine can arrive at any time
+ * while @intf is resumed and its usage counter is equal to 0.  They are
+ * not protected by the usb_device's lock but only by its pm_mutex.
+ * Drivers must provide their own synchronization.
+ *
+ * This routine can run only in process context.
+ */
+void usb_autopm_put_interface(struct usb_interface *intf)
+{
+	struct usb_device	*udev = interface_to_usbdev(intf);
+
+	usb_pm_lock(udev);
+	if (intf->condition != USB_INTERFACE_UNBOUND &&
+			--intf->pm_usage_cnt <= 0) {
+		queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+				USB_AUTOSUSPEND_DELAY);
+	}
+	usb_pm_unlock(udev);
+	// dev_dbg(&intf->dev, "%s: cnt %d\n",
+	//		__FUNCTION__, intf->pm_usage_cnt);
+}
+EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+
+/**
+ * usb_autopm_get_interface - increment a USB interface's PM-usage counter
+ * @intf: the usb_interface whose counter should be incremented
+ *
+ * This routine should be called by an interface driver when it wants to
+ * use @intf and needs to guarantee that it is not suspended.  In addition,
+ * the routine prevents @intf from being autosuspended subsequently.  (Note
+ * that this will not prevent suspend events originating in the PM core.)
+ * This prevention will persist until usb_autopm_put_interface() is called
+ * or @intf is unbound.  A typical example would be a character-device
+ * driver when its device file is opened.
+ *
+ * The routine increments @intf's usage counter.  So long as the counter
+ * is greater than 0, autosuspend will not be allowed for @intf or its
+ * usb_device.  When the driver is finished using @intf it should call
+ * usb_autopm_put_interface() to decrement the usage counter and queue
+ * a delayed autosuspend request (if the counter is <= 0).
+ *
+ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+ * core will not change its value other than the increment and decrement
+ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+ * may use this simple counter-oriented discipline or may set the value
+ * any way it likes.
+ *
+ * Resume method calls generated by this routine can arrive at any time
+ * while @intf is suspended.  They are not protected by the usb_device's
+ * lock but only by its pm_mutex.  Drivers must provide their own
+ * synchronization.
+ *
+ * This routine can run only in process context.
+ */
+int usb_autopm_get_interface(struct usb_interface *intf)
+{
+	struct usb_device	*udev = interface_to_usbdev(intf);
+	int			status;
+
+	usb_pm_lock(udev);
+	if (intf->condition == USB_INTERFACE_UNBOUND)
+		status = -ENODEV;
+	else {
+		++intf->pm_usage_cnt;
+		udev->auto_pm = 1;
+		status = usb_resume_both(udev);
+		if (status != 0)
+			--intf->pm_usage_cnt;
+	}
+	usb_pm_unlock(udev);
+	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+	//		__FUNCTION__, status, intf->pm_usage_cnt);
+	return status;
+}
+EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+
+#endif /* CONFIG_USB_SUSPEND */
+
+static int usb_suspend(struct device *dev, pm_message_t message)
+{
+	int	status;
+
+	if (is_usb_device(dev)) {
+		struct usb_device *udev = to_usb_device(dev);
+
+		usb_pm_lock(udev);
+		udev->auto_pm = 0;
+		status = usb_suspend_both(udev, message);
+		usb_pm_unlock(udev);
+	} else
+		status = 0;
+	return status;
+}
+
+static int usb_resume(struct device *dev)
+{
+	int	status;
+
+	if (is_usb_device(dev)) {
+		struct usb_device *udev = to_usb_device(dev);
+
+		usb_pm_lock(udev);
+		udev->auto_pm = 0;
+		status = usb_resume_both(udev);
+		usb_pm_unlock(udev);
+
+		/* Rebind drivers that had no suspend method? */
+	} else
+		status = 0;
+	return status;
+}
+
+#endif /* CONFIG_PM */
+
+struct bus_type usb_bus_type = {
+	.name =		"usb",
+	.match =	usb_device_match,
+	.uevent =	usb_uevent,
+#ifdef CONFIG_PM
+	.suspend =	usb_suspend,
+	.resume =	usb_resume,
+#endif
+};
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 247b5a4..3ebb901 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -207,9 +207,9 @@
 	kfree(ep_dev);
 }
 
-void usb_create_ep_files(struct device *parent,
-			 struct usb_host_endpoint *endpoint,
-			 struct usb_device *udev)
+int usb_create_ep_files(struct device *parent,
+			struct usb_host_endpoint *endpoint,
+			struct usb_device *udev)
 {
 	char name[8];
 	struct ep_device *ep_dev;
@@ -242,19 +242,33 @@
 	retval = device_register(&ep_dev->dev);
 	if (retval)
 		goto error;
-	sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+	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);
-	sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name);
-
+	retval = sysfs_create_link(&parent->kobj,
+				   &endpoint->ep_dev->dev.kobj, name);
+	if (retval)
+		goto error_link;
 exit:
-	return;
+	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:
 	kfree(ep_dev);
-	return;
+	destroy_endpoint_class();
+	return retval;
 }
 
 void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 8de4f8c..c376c65 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -55,7 +55,7 @@
 	return err;
 }
 
-static struct file_operations usb_fops = {
+static const struct file_operations usb_fops = {
 	.owner =	THIS_MODULE,
 	.open =		usb_open,
 };
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
new file mode 100644
index 0000000..16332cc
--- /dev/null
+++ b/drivers/usb/core/generic.c
@@ -0,0 +1,208 @@
+/*
+ * drivers/usb/generic.c - generic driver for USB devices (not interfaces)
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * based on drivers/usb/usb.c which had the following copyrights:
+ *	(C) Copyright Linus Torvalds 1999
+ *	(C) Copyright Johannes Erdfelt 1999-2001
+ *	(C) Copyright Andreas Gal 1999
+ *	(C) Copyright Gregory P. Smith 1999
+ *	(C) Copyright Deti Fliegl 1999 (new USB architecture)
+ *	(C) Copyright Randy Dunlap 2000
+ *	(C) Copyright David Brownell 2000-2004
+ *	(C) Copyright Yggdrasil Computing, Inc. 2000
+ *		(usb_device_id matching changes by Adam J. Richter)
+ *	(C) Copyright Greg Kroah-Hartman 2002-2003
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/usb.h>
+#include "usb.h"
+
+static inline const char *plural(int n)
+{
+	return (n == 1 ? "" : "s");
+}
+
+static int choose_configuration(struct usb_device *udev)
+{
+	int i;
+	int num_configs;
+	int insufficient_power = 0;
+	struct usb_host_config *c, *best;
+
+	best = NULL;
+	c = udev->config;
+	num_configs = udev->descriptor.bNumConfigurations;
+	for (i = 0; i < num_configs; (i++, c++)) {
+		struct usb_interface_descriptor	*desc = NULL;
+
+		/* It's possible that a config has no interfaces! */
+		if (c->desc.bNumInterfaces > 0)
+			desc = &c->intf_cache[0]->altsetting->desc;
+
+		/*
+		 * HP's USB bus-powered keyboard has only one configuration
+		 * and it claims to be self-powered; other devices may have
+		 * similar errors in their descriptors.  If the next test
+		 * were allowed to execute, such configurations would always
+		 * be rejected and the devices would not work as expected.
+		 * In the meantime, we run the risk of selecting a config
+		 * that requires external power at a time when that power
+		 * isn't available.  It seems to be the lesser of two evils.
+		 *
+		 * Bugzilla #6448 reports a device that appears to crash
+		 * when it receives a GET_DEVICE_STATUS request!  We don't
+		 * have any other way to tell whether a device is self-powered,
+		 * but since we don't use that information anywhere but here,
+		 * the call has been removed.
+		 *
+		 * Maybe the GET_DEVICE_STATUS call and the test below can
+		 * be reinstated when device firmwares become more reliable.
+		 * Don't hold your breath.
+		 */
+#if 0
+		/* Rule out self-powered configs for a bus-powered device */
+		if (bus_powered && (c->desc.bmAttributes &
+					USB_CONFIG_ATT_SELFPOWER))
+			continue;
+#endif
+
+		/*
+		 * The next test may not be as effective as it should be.
+		 * Some hubs have errors in their descriptor, claiming
+		 * to be self-powered when they are really bus-powered.
+		 * We will overestimate the amount of current such hubs
+		 * make available for each port.
+		 *
+		 * This is a fairly benign sort of failure.  It won't
+		 * cause us to reject configurations that we should have
+		 * accepted.
+		 */
+
+		/* Rule out configs that draw too much bus current */
+		if (c->desc.bMaxPower * 2 > udev->bus_mA) {
+			insufficient_power++;
+			continue;
+		}
+
+		/* If the first config's first interface is COMM/2/0xff
+		 * (MSFT RNDIS), rule it out unless Linux has host-side
+		 * RNDIS support. */
+		if (i == 0 && desc
+				&& desc->bInterfaceClass == USB_CLASS_COMM
+				&& desc->bInterfaceSubClass == 2
+				&& desc->bInterfaceProtocol == 0xff) {
+#ifndef CONFIG_USB_NET_RNDIS_HOST
+			continue;
+#else
+			best = c;
+#endif
+		}
+
+		/* From the remaining configs, choose the first one whose
+		 * first interface is for a non-vendor-specific class.
+		 * Reason: Linux is more likely to have a class driver
+		 * than a vendor-specific driver. */
+		else if (udev->descriptor.bDeviceClass !=
+						USB_CLASS_VENDOR_SPEC &&
+				(!desc || desc->bInterfaceClass !=
+						USB_CLASS_VENDOR_SPEC)) {
+			best = c;
+			break;
+		}
+
+		/* If all the remaining configs are vendor-specific,
+		 * choose the first one. */
+		else if (!best)
+			best = c;
+	}
+
+	if (insufficient_power > 0)
+		dev_info(&udev->dev, "rejected %d configuration%s "
+			"due to insufficient available bus power\n",
+			insufficient_power, plural(insufficient_power));
+
+	if (best) {
+		i = best->desc.bConfigurationValue;
+		dev_info(&udev->dev,
+			"configuration #%d chosen from %d choice%s\n",
+			i, num_configs, plural(num_configs));
+	} else {
+		i = -1;
+		dev_warn(&udev->dev,
+			"no configuration chosen from %d choice%s\n",
+			num_configs, plural(num_configs));
+	}
+	return i;
+}
+
+static int generic_probe(struct usb_device *udev)
+{
+	int err, c;
+
+	/* put device-specific files into sysfs */
+	usb_create_sysfs_dev_files(udev);
+
+	/* Choose and set the configuration.  This registers the interfaces
+	 * with the driver core and lets interface drivers bind to them.
+	 */
+	c = choose_configuration(udev);
+	if (c >= 0) {
+		err = usb_set_configuration(udev, c);
+		if (err) {
+			dev_err(&udev->dev, "can't set config #%d, error %d\n",
+					c, err);
+			/* This need not be fatal.  The user can try to
+			 * set other configurations. */
+		}
+	}
+
+	/* USB device state == configured ... usable */
+	usb_notify_add_device(udev);
+
+	return 0;
+}
+
+static void generic_disconnect(struct usb_device *udev)
+{
+	usb_notify_remove_device(udev);
+
+	/* if this is only an unbind, not a physical disconnect, then
+	 * unconfigure the device */
+	if (udev->actconfig)
+		usb_set_configuration(udev, 0);
+
+	usb_remove_sysfs_dev_files(udev);
+}
+
+#ifdef	CONFIG_PM
+
+static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+{
+	/* USB devices enter SUSPEND state through their hubs, but can be
+	 * marked for FREEZE as soon as their children are already idled.
+	 * But those semantics are useless, so we equate the two (sigh).
+	 */
+	return usb_port_suspend(udev);
+}
+
+static int generic_resume(struct usb_device *udev)
+{
+	return usb_port_resume(udev);
+}
+
+#endif	/* CONFIG_PM */
+
+struct usb_device_driver usb_generic_driver = {
+	.name =	"usb",
+	.probe = generic_probe,
+	.disconnect = generic_disconnect,
+#ifdef	CONFIG_PM
+	.suspend = generic_suspend,
+	.resume = generic_resume,
+#endif
+	.supports_autosuspend = 1,
+};
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index fa36391..edf4300 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -413,4 +413,20 @@
 
 #endif	/* CONFIG_PM */
 
+/**
+ * usb_hcd_pci_shutdown - shutdown host controller
+ * @dev: USB Host Controller being shutdown
+ */
+void usb_hcd_pci_shutdown (struct pci_dev *dev)
+{
+	struct usb_hcd		*hcd;
+
+	hcd = pci_get_drvdata(dev);
+	if (!hcd)
+		return;
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+}
+EXPORT_SYMBOL (usb_hcd_pci_shutdown);
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fb4d058..37f9f5e7 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -36,6 +36,7 @@
 #include <linux/mutex.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
+#include <linux/platform_device.h>
 
 #include <linux/usb.h>
 
@@ -344,7 +345,8 @@
 	struct usb_ctrlrequest *cmd;
  	u16		typeReq, wValue, wIndex, wLength;
 	u8		*ubuf = urb->transfer_buffer;
-	u8		tbuf [sizeof (struct usb_hub_descriptor)];
+	u8		tbuf [sizeof (struct usb_hub_descriptor)]
+		__attribute__((aligned(4)));
 	const u8	*bufp = tbuf;
 	int		len = 0;
 	int		patch_wakeup = 0;
@@ -632,31 +634,20 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* Asynchronous unlinks of root-hub control URBs are legal, but they
- * don't do anything.  Status URB unlinks must be made in process context
- * with interrupts enabled.
+/* Unlinks of root-hub control URBs are legal, but they don't do anything
+ * since these URBs always execute synchronously.
  */
 static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
+	unsigned long	flags;
+
 	if (usb_pipeendpoint(urb->pipe) == 0) {	/* Control URB */
-		if (in_interrupt())
-			return 0;		/* nothing to do */
-
-		spin_lock_irq(&urb->lock);	/* from usb_kill_urb */
-		++urb->reject;
-		spin_unlock_irq(&urb->lock);
-
-		wait_event(usb_kill_urb_queue,
-				atomic_read(&urb->use_count) == 0);
-
-		spin_lock_irq(&urb->lock);
-		--urb->reject;
-		spin_unlock_irq(&urb->lock);
+		;	/* Do nothing */
 
 	} else {				/* Status URB */
 		if (!hcd->uses_new_polling)
-			del_timer_sync (&hcd->rh_timer);
-		local_irq_disable ();
+			del_timer (&hcd->rh_timer);
+		local_irq_save (flags);
 		spin_lock (&hcd_root_hub_lock);
 		if (urb == hcd->status_urb) {
 			hcd->status_urb = NULL;
@@ -666,7 +657,7 @@
 		spin_unlock (&hcd_root_hub_lock);
 		if (urb)
 			usb_hcd_giveback_urb (hcd, urb, NULL);
-		local_irq_enable ();
+		local_irq_restore (flags);
 	}
 
 	return 0;
@@ -674,31 +665,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* exported only within usbcore */
-struct usb_bus *usb_bus_get(struct usb_bus *bus)
-{
-	if (bus)
-		kref_get(&bus->kref);
-	return bus;
-}
-
-static void usb_host_release(struct kref *kref)
-{
-	struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
-
-	if (bus->release)
-		bus->release(bus);
-}
-
-/* exported only within usbcore */
-void usb_bus_put(struct usb_bus *bus)
-{
-	if (bus)
-		kref_put(&bus->kref, usb_host_release);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static struct class *usb_host_class;
 
 int usb_host_init(void)
@@ -730,39 +696,12 @@
 	bus->devnum_next = 1;
 
 	bus->root_hub = NULL;
-	bus->hcpriv = NULL;
 	bus->busnum = -1;
 	bus->bandwidth_allocated = 0;
 	bus->bandwidth_int_reqs  = 0;
 	bus->bandwidth_isoc_reqs = 0;
 
 	INIT_LIST_HEAD (&bus->bus_list);
-
-	kref_init(&bus->kref);
-}
-
-/**
- * usb_alloc_bus - creates a new USB host controller structure
- * @op: pointer to a struct usb_operations that this bus structure should use
- * Context: !in_interrupt()
- *
- * Creates a USB host controller bus structure with the specified 
- * usb_operations and initializes all the necessary internal objects.
- *
- * If no memory is available, NULL is returned.
- *
- * The caller should call usb_put_bus() when it is finished with the structure.
- */
-struct usb_bus *usb_alloc_bus (struct usb_operations *op)
-{
-	struct usb_bus *bus;
-
-	bus = kzalloc (sizeof *bus, GFP_KERNEL);
-	if (!bus)
-		return NULL;
-	usb_bus_init (bus);
-	bus->op = op;
-	return bus;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -897,8 +836,7 @@
 	struct usb_hcd *hcd;
 
 	hcd = container_of (bus, struct usb_hcd, self);
-	if (hcd->driver->hub_irq_enable && !hcd->poll_rh &&
-			hcd->state != HC_STATE_HALT)
+	if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
 		hcd->driver->hub_irq_enable (hcd);
 }
 
@@ -1112,10 +1050,10 @@
  * expects usb_submit_urb() to have sanity checked and conditioned all
  * inputs in the urb
  */
-static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 {
 	int			status;
-	struct usb_hcd		*hcd = urb->dev->bus->hcpriv;
+	struct usb_hcd		*hcd = bus_to_hcd(urb->dev->bus);
 	struct usb_host_endpoint *ep;
 	unsigned long		flags;
 
@@ -1186,7 +1124,7 @@
 	/* lower level hcd code should use *_dma exclusively,
 	 * unless it uses pio or talks to another transport.
 	 */
-	if (hcd->self.controller->dma_mask) {
+	if (hcd->self.uses_dma) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
 			urb->setup_dma = dma_map_single (
@@ -1221,9 +1159,10 @@
 /*-------------------------------------------------------------------------*/
 
 /* called in any context */
-static int hcd_get_frame_number (struct usb_device *udev)
+int usb_hcd_get_frame_number (struct usb_device *udev)
 {
-	struct usb_hcd	*hcd = (struct usb_hcd *)udev->bus->hcpriv;
+	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);
+
 	if (!HC_IS_RUNNING (hcd->state))
 		return -ESHUTDOWN;
 	return hcd->driver->get_frame_number (hcd);
@@ -1263,7 +1202,7 @@
  * caller guarantees urb won't be recycled till both unlink()
  * and the urb's completion function return
  */
-static int hcd_unlink_urb (struct urb *urb, int status)
+int usb_hcd_unlink_urb (struct urb *urb, int status)
 {
 	struct usb_host_endpoint	*ep;
 	struct usb_hcd			*hcd = NULL;
@@ -1296,7 +1235,7 @@
 	spin_lock (&hcd_data_lock);
 
 	sys = &urb->dev->dev;
-	hcd = urb->dev->bus->hcpriv;
+	hcd = bus_to_hcd(urb->dev->bus);
 	if (hcd == NULL) {
 		retval = -ENODEV;
 		goto done;
@@ -1354,41 +1293,33 @@
 /*-------------------------------------------------------------------------*/
 
 /* disables the endpoint: cancels any pending urbs, then synchronizes with
- * the hcd to make sure all endpoint state is gone from hardware. use for
+ * the hcd to make sure all endpoint state is gone from hardware, and then
+ * waits until the endpoint's queue is completely drained. use for
  * set_configuration, set_interface, driver removal, physical disconnect.
  *
  * example:  a qh stored in ep->hcpriv, holding state related to endpoint
  * type, maxpacket size, toggle, halt status, and scheduling.
  */
-static void
-hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
+void usb_hcd_endpoint_disable (struct usb_device *udev,
+		struct usb_host_endpoint *ep)
 {
 	struct usb_hcd		*hcd;
 	struct urb		*urb;
 
-	hcd = udev->bus->hcpriv;
+	hcd = bus_to_hcd(udev->bus);
 
 	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
 			udev->state != USB_STATE_NOTATTACHED);
 
 	local_irq_disable ();
 
-	/* FIXME move most of this into message.c as part of its
-	 * endpoint disable logic
-	 */
-
 	/* ep is already gone from udev->ep_{in,out}[]; no more submits */
 rescan:
 	spin_lock (&hcd_data_lock);
 	list_for_each_entry (urb, &ep->urb_list, urb_list) {
 		int	tmp;
 
-		/* another cpu may be in hcd, spinning on hcd_data_lock
-		 * to giveback() this urb.  the races here should be
-		 * small, but a full fix needs a new "can't submit"
-		 * urb state.
-		 * FIXME urb->reject should allow that...
-		 */
+		/* the urb may already have been unlinked */
 		if (urb->status != -EINPROGRESS)
 			continue;
 		usb_get_urb (urb);
@@ -1430,6 +1361,30 @@
 	might_sleep ();
 	if (hcd->driver->endpoint_disable)
 		hcd->driver->endpoint_disable (hcd, ep);
+
+	/* Wait until the endpoint queue is completely empty.  Most HCDs
+	 * will have done this already in their endpoint_disable method,
+	 * but some might not.  And there could be root-hub control URBs
+	 * still pending since they aren't affected by the HCDs'
+	 * endpoint_disable methods.
+	 */
+	while (!list_empty (&ep->urb_list)) {
+		spin_lock_irq (&hcd_data_lock);
+
+		/* The list may have changed while we acquired the spinlock */
+		urb = NULL;
+		if (!list_empty (&ep->urb_list)) {
+			urb = list_entry (ep->urb_list.prev, struct urb,
+					urb_list);
+			usb_get_urb (urb);
+		}
+		spin_unlock_irq (&hcd_data_lock);
+
+		if (urb) {
+			usb_kill_urb (urb);
+			usb_put_urb (urb);
+		}
+	}
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1476,50 +1431,6 @@
 	return status;
 }
 
-/*
- * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
- * @hcd: host controller for this root hub
- *
- * This call arranges that usb_hcd_resume_root_hub() is safe to call later;
- * that the HCD's root hub polling is deactivated; and that the root's hub
- * driver is suspended.  HCDs may call this to autosuspend when their root
- * hub's downstream ports are all inactive:  unpowered, disconnected,
- * disabled, or suspended.
- *
- * The HCD will autoresume on device connect change detection (using SRP
- * or a D+/D- pullup).  The HCD also autoresumes on remote wakeup signaling
- * from any ports that are suspended (if that is enabled).  In most cases,
- * overcurrent signaling (on powered ports) will also start autoresume.
- *
- * Always called with IRQs blocked.
- */
-void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
-{
-	struct urb	*urb;
-
-	spin_lock (&hcd_root_hub_lock);
-	usb_suspend_root_hub (hcd->self.root_hub);
-
-	/* force status urb to complete/unlink while suspended */
-	if (hcd->status_urb) {
-		urb = hcd->status_urb;
-		urb->status = -ECONNRESET;
-		urb->hcpriv = NULL;
-		urb->actual_length = 0;
-
-		del_timer (&hcd->rh_timer);
-		hcd->poll_pending = 0;
-		hcd->status_urb = NULL;
-	} else
-		urb = NULL;
-	spin_unlock (&hcd_root_hub_lock);
-	hcd->state = HC_STATE_SUSPENDED;
-
-	if (urb)
-		usb_hcd_giveback_urb (hcd, urb, NULL);
-}
-EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
-
 /**
  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
  * @hcd: host controller for this root hub
@@ -1583,20 +1494,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue)
- */
-static struct usb_operations usb_hcd_operations = {
-	.get_frame_number =	hcd_get_frame_number,
-	.submit_urb =		hcd_submit_urb,
-	.unlink_urb =		hcd_unlink_urb,
-	.buffer_alloc =		hcd_buffer_alloc,
-	.buffer_free =		hcd_buffer_free,
-	.disable =		hcd_endpoint_disable,
-};
-
-/*-------------------------------------------------------------------------*/
-
 /**
  * usb_hcd_giveback_urb - return URB from HCD to device driver
  * @hcd: host controller returning the URB
@@ -1617,8 +1514,9 @@
 	at_root_hub = (urb->dev == hcd->self.root_hub);
 	urb_unlink (urb);
 
-	/* lower level hcd code should use *_dma exclusively */
-	if (hcd->self.controller->dma_mask && !at_root_hub) {
+	/* lower level hcd code should use *_dma exclusively if the
+	 * host controller does DMA */
+	if (hcd->self.uses_dma && !at_root_hub) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
 			dma_unmap_single (hcd->self.controller, urb->setup_dma,
@@ -1704,14 +1602,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void hcd_release (struct usb_bus *bus)
-{
-	struct usb_hcd *hcd;
-
-	hcd = container_of(bus, struct usb_hcd, self);
-	kfree(hcd);
-}
-
 /**
  * usb_create_hcd - create and initialize an HCD structure
  * @driver: HC driver that will use this hcd
@@ -1736,13 +1626,12 @@
 		return NULL;
 	}
 	dev_set_drvdata(dev, hcd);
+	kref_init(&hcd->kref);
 
 	usb_bus_init(&hcd->self);
-	hcd->self.op = &usb_hcd_operations;
-	hcd->self.hcpriv = hcd;
-	hcd->self.release = &hcd_release;
 	hcd->self.controller = dev;
 	hcd->self.bus_name = bus_name;
+	hcd->self.uses_dma = (dev->dma_mask != NULL);
 
 	init_timer(&hcd->rh_timer);
 	hcd->rh_timer.function = rh_timer_func;
@@ -1756,10 +1645,25 @@
 }
 EXPORT_SYMBOL (usb_create_hcd);
 
+static void hcd_release (struct kref *kref)
+{
+	struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
+
+	kfree(hcd);
+}
+
+struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
+{
+	if (hcd)
+		kref_get (&hcd->kref);
+	return hcd;
+}
+EXPORT_SYMBOL (usb_get_hcd);
+
 void usb_put_hcd (struct usb_hcd *hcd)
 {
-	dev_set_drvdata(hcd->self.controller, NULL);
-	usb_bus_put(&hcd->self);
+	if (hcd)
+		kref_put (&hcd->kref, hcd_release);
 }
 EXPORT_SYMBOL (usb_put_hcd);
 
@@ -1915,6 +1819,16 @@
 }
 EXPORT_SYMBOL (usb_remove_hcd);
 
+void
+usb_hcd_platform_shutdown(struct platform_device* dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+}
+EXPORT_SYMBOL (usb_hcd_platform_shutdown);
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_USB_MON)
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 7022aaf..676877c 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -55,12 +55,13 @@
 
 /*-------------------------------------------------------------------------*/
 
-struct usb_hcd {	/* usb_bus.hcpriv points to this */
+struct usb_hcd {
 
 	/*
 	 * housekeeping
 	 */
 	struct usb_bus		self;		/* hcd is-a bus */
+	struct kref		kref;		/* reference counter */
 
 	const char		*product_desc;	/* product/vendor string */
 	char			irq_descr[24];	/* driver + bus # */
@@ -85,6 +86,7 @@
 	unsigned		uses_new_polling:1;
 	unsigned		poll_rh:1;	/* poll for rh status? */
 	unsigned		poll_pending:1;	/* status has changed? */
+	unsigned		wireless:1;	/* Wireless USB HCD */
 
 	int			irq;		/* irq allocated */
 	void __iomem		*regs;		/* device memory/io */
@@ -128,8 +130,10 @@
 	return &hcd->self;
 }
 
-
-// urb.hcpriv is really hardware-specific
+static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
+{
+	return container_of(bus, struct usb_hcd, self);
+}
 
 struct hcd_timeout {	/* timeouts we allocate */
 	struct list_head	timeout_list;
@@ -138,28 +142,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * FIXME usb_operations should vanish or become hc_driver,
- * when usb_bus and usb_hcd become the same thing.
- */
-
-struct usb_operations {
-	int (*get_frame_number) (struct usb_device *usb_dev);
-	int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
-	int (*unlink_urb) (struct urb *urb, int status);
-
-	/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
-	void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
-			gfp_t mem_flags,
-			dma_addr_t *dma);
-	void (*buffer_free)(struct usb_bus *bus, size_t size,
-			void *addr, dma_addr_t dma);
-
-	void (*disable)(struct usb_device *udev,
-			struct usb_host_endpoint *ep);
-};
-
-/* each driver provides one of these, and hardware init support */
 
 struct pt_regs;
 
@@ -192,6 +174,9 @@
 	/* cleanly make HCD stop writing memory and doing I/O */
 	void	(*stop) (struct usb_hcd *hcd);
 
+	/* shutdown HCD */
+	void	(*shutdown) (struct usb_hcd *hcd);
+
 	/* return current frame number */
 	int	(*get_frame_number) (struct usb_hcd *hcd);
 
@@ -218,15 +203,25 @@
 		/* Needed only if port-change IRQs are level-triggered */
 };
 
-extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
+extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
+extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb,
+		struct pt_regs *regs);
+extern void usb_hcd_endpoint_disable (struct usb_device *udev,
+		struct usb_host_endpoint *ep);
+extern int usb_hcd_get_frame_number (struct usb_device *udev);
 
 extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 		struct device *dev, char *bus_name);
+extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
 extern void usb_put_hcd (struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
 		unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
 
+struct platform_device;
+extern void usb_hcd_platform_shutdown(struct platform_device* dev);
+
 #ifdef CONFIG_PCI
 struct pci_dev;
 struct pci_device_id;
@@ -239,6 +234,8 @@
 extern int usb_hcd_pci_resume (struct pci_dev *dev);
 #endif /* CONFIG_PM */
 
+extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
+
 #endif /* CONFIG_PCI */
 
 /* pci-ish (pdev null is ok) buffer alloc/mapping support */
@@ -352,8 +349,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-
 extern void usb_set_device_state(struct usb_device *udev,
 		enum usb_device_state new_state);
 
@@ -365,9 +360,6 @@
 extern struct mutex usb_bus_list_lock;
 extern wait_queue_head_t usb_kill_urb_queue;
 
-extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
-extern void usb_bus_put (struct usb_bus *bus);
-
 extern void usb_enable_root_hub_irq (struct usb_bus *bus);
 
 extern int usb_find_interface_driver (struct usb_device *dev,
@@ -376,17 +368,11 @@
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
 #ifdef CONFIG_PM
-extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
 extern void usb_root_hub_lost_power (struct usb_device *rhdev);
 extern int hcd_bus_suspend (struct usb_bus *bus);
 extern int hcd_bus_resume (struct usb_bus *bus);
 #else
-static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
-{
-	return;
-}
-
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
 	return;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 26c8cb5..7676690 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -293,7 +293,7 @@
 /* completion function, fires on port status changes and various faults */
 static void hub_irq(struct urb *urb, struct pt_regs *regs)
 {
-	struct usb_hub *hub = (struct usb_hub *)urb->context;
+	struct usb_hub *hub = urb->context;
 	int status;
 	int i;
 	unsigned long bits;
@@ -311,7 +311,7 @@
 			goto resubmit;
 		hub->error = urb->status;
 		/* FALL THROUGH */
-	
+
 	/* let khubd handle things */
 	case 0:			/* we got data:  port status changed */
 		bits = 0;
@@ -452,18 +452,14 @@
 	msleep(max(pgood_delay, (unsigned) 100));
 }
 
-static inline void __hub_quiesce(struct usb_hub *hub)
+static void hub_quiesce(struct usb_hub *hub)
 {
 	/* (nonblocking) khubd and related activity won't re-trigger */
 	hub->quiescing = 1;
 	hub->activating = 0;
 	hub->resume_root_hub = 0;
-}
 
-static void hub_quiesce(struct usb_hub *hub)
-{
 	/* (blocking) stop khubd and related activity */
-	__hub_quiesce(hub);
 	usb_kill_urb(hub->urb);
 	if (hub->has_indicators)
 		cancel_delayed_work(&hub->leds);
@@ -868,13 +864,8 @@
 
 	endpoint = &desc->endpoint[0].desc;
 
-	/* Output endpoint? Curiouser and curiouser.. */
-	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-		goto descriptor_error;
-
-	/* If it's not an interrupt endpoint, we'd better punt! */
-	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			!= USB_ENDPOINT_XFER_INT)
+	/* If it's not an interrupt in endpoint, we'd better punt! */
+	if (!usb_endpoint_is_int_in(endpoint))
 		goto descriptor_error;
 
 	/* We found a hub */
@@ -1022,26 +1013,29 @@
 	if (udev->state == USB_STATE_NOTATTACHED)
 		;	/* do nothing */
 	else if (new_state != USB_STATE_NOTATTACHED) {
-		udev->state = new_state;
 
 		/* root hub wakeup capabilities are managed out-of-band
 		 * and may involve silicon errata ... ignore them here.
 		 */
 		if (udev->parent) {
-			if (new_state == USB_STATE_CONFIGURED)
+			if (udev->state == USB_STATE_SUSPENDED
+					|| new_state == USB_STATE_SUSPENDED)
+				;	/* No change to wakeup settings */
+			else if (new_state == USB_STATE_CONFIGURED)
 				device_init_wakeup(&udev->dev,
 					(udev->actconfig->desc.bmAttributes
 					 & USB_CONFIG_ATT_WAKEUP));
-			else if (new_state != USB_STATE_SUSPENDED)
+			else
 				device_init_wakeup(&udev->dev, 0);
 		}
+		udev->state = new_state;
 	} else
 		recursively_mark_NOTATTACHED(udev);
 	spin_unlock_irqrestore(&device_state_lock, flags);
 }
 
 
-#ifdef CONFIG_PM
+#ifdef	CONFIG_PM
 
 /**
  * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
@@ -1059,6 +1053,12 @@
 	unsigned long flags;
 
 	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+
+	/* Make sure no potential wakeup events get lost,
+	 * by forcing the root hub to be resumed.
+	 */
+	rhdev->dev.power.prev_state.event = PM_EVENT_ON;
+
 	spin_lock_irqsave(&device_state_lock, flags);
 	hub = hdev_to_hub(rhdev);
 	for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
@@ -1072,7 +1072,7 @@
 }
 EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
 
-#endif
+#endif	/* CONFIG_PM */
 
 static void choose_address(struct usb_device *udev)
 {
@@ -1148,144 +1148,28 @@
 	 * cleaning up all state associated with the current configuration
 	 * so that the hardware is now fully quiesced.
 	 */
+	dev_dbg (&udev->dev, "unregistering device\n");
 	usb_disable_device(udev, 0);
 
-	usb_notify_remove_device(udev);
+	usb_unlock_device(udev);
 
-	/* Free the device number, remove the /proc/bus/usb entry and
-	 * the sysfs attributes, and delete the parent's children[]
+	/* Unregister the device.  The device driver is responsible
+	 * for removing the device files from usbfs and sysfs and for
+	 * de-configuring the device.
+	 */
+	device_del(&udev->dev);
+
+	/* Free the device number and delete the parent's children[]
 	 * (or root_hub) pointer.
 	 */
-	dev_dbg (&udev->dev, "unregistering device\n");
 	release_address(udev);
-	usb_remove_sysfs_dev_files(udev);
 
 	/* Avoid races with recursively_mark_NOTATTACHED() */
 	spin_lock_irq(&device_state_lock);
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
 
-	usb_unlock_device(udev);
-
-	device_unregister(&udev->dev);
-}
-
-static inline const char *plural(int n)
-{
-	return (n == 1 ? "" : "s");
-}
-
-static int choose_configuration(struct usb_device *udev)
-{
-	int i;
-	int num_configs;
-	int insufficient_power = 0;
-	struct usb_host_config *c, *best;
-
-	best = NULL;
-	c = udev->config;
-	num_configs = udev->descriptor.bNumConfigurations;
-	for (i = 0; i < num_configs; (i++, c++)) {
-		struct usb_interface_descriptor	*desc = NULL;
-
-		/* It's possible that a config has no interfaces! */
-		if (c->desc.bNumInterfaces > 0)
-			desc = &c->intf_cache[0]->altsetting->desc;
-
-		/*
-		 * HP's USB bus-powered keyboard has only one configuration
-		 * and it claims to be self-powered; other devices may have
-		 * similar errors in their descriptors.  If the next test
-		 * were allowed to execute, such configurations would always
-		 * be rejected and the devices would not work as expected.
-		 * In the meantime, we run the risk of selecting a config
-		 * that requires external power at a time when that power
-		 * isn't available.  It seems to be the lesser of two evils.
-		 *
-		 * Bugzilla #6448 reports a device that appears to crash
-		 * when it receives a GET_DEVICE_STATUS request!  We don't
-		 * have any other way to tell whether a device is self-powered,
-		 * but since we don't use that information anywhere but here,
-		 * the call has been removed.
-		 *
-		 * Maybe the GET_DEVICE_STATUS call and the test below can
-		 * be reinstated when device firmwares become more reliable.
-		 * Don't hold your breath.
-		 */
-#if 0
-		/* Rule out self-powered configs for a bus-powered device */
-		if (bus_powered && (c->desc.bmAttributes &
-					USB_CONFIG_ATT_SELFPOWER))
-			continue;
-#endif
-
-		/*
-		 * The next test may not be as effective as it should be.
-		 * Some hubs have errors in their descriptor, claiming
-		 * to be self-powered when they are really bus-powered.
-		 * We will overestimate the amount of current such hubs
-		 * make available for each port.
-		 *
-		 * This is a fairly benign sort of failure.  It won't
-		 * cause us to reject configurations that we should have
-		 * accepted.
-		 */
-
-		/* Rule out configs that draw too much bus current */
-		if (c->desc.bMaxPower * 2 > udev->bus_mA) {
-			insufficient_power++;
-			continue;
-		}
-
-		/* If the first config's first interface is COMM/2/0xff
-		 * (MSFT RNDIS), rule it out unless Linux has host-side
-		 * RNDIS support. */
-		if (i == 0 && desc
-				&& desc->bInterfaceClass == USB_CLASS_COMM
-				&& desc->bInterfaceSubClass == 2
-				&& desc->bInterfaceProtocol == 0xff) {
-#ifndef CONFIG_USB_NET_RNDIS_HOST
-			continue;
-#else
-			best = c;
-#endif
-		}
-
-		/* From the remaining configs, choose the first one whose
-		 * first interface is for a non-vendor-specific class.
-		 * Reason: Linux is more likely to have a class driver
-		 * than a vendor-specific driver. */
-		else if (udev->descriptor.bDeviceClass !=
-						USB_CLASS_VENDOR_SPEC &&
-				(!desc || desc->bInterfaceClass !=
-						USB_CLASS_VENDOR_SPEC)) {
-			best = c;
-			break;
-		}
-
-		/* If all the remaining configs are vendor-specific,
-		 * choose the first one. */
-		else if (!best)
-			best = c;
-	}
-
-	if (insufficient_power > 0)
-		dev_info(&udev->dev, "rejected %d configuration%s "
-			"due to insufficient available bus power\n",
-			insufficient_power, plural(insufficient_power));
-
-	if (best) {
-		i = best->desc.bConfigurationValue;
-		dev_info(&udev->dev,
-			"configuration #%d chosen from %d choice%s\n",
-			i, num_configs, plural(num_configs));
-	} else {
-		i = -1;
-		dev_warn(&udev->dev,
-			"no configuration chosen from %d choice%s\n",
-			num_configs, plural(num_configs));
-	}
-	return i;
+	put_device(&udev->dev);
 }
 
 #ifdef DEBUG
@@ -1328,7 +1212,6 @@
 int usb_new_device(struct usb_device *udev)
 {
 	int err;
-	int c;
 
 	err = usb_get_configuration(udev);
 	if (err < 0) {
@@ -1371,8 +1254,7 @@
 					USB_DT_OTG, (void **) &desc) == 0) {
 			if (desc->bmAttributes & USB_OTG_HNP) {
 				unsigned		port1 = udev->portnum;
-				struct usb_device	*root = udev->parent;
-				
+
 				dev_info(&udev->dev,
 					"Dual-Role OTG device on %sHNP port\n",
 					(port1 == bus->otg_port)
@@ -1407,9 +1289,9 @@
 		 * (Includes HNP test device.)
 		 */
 		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-			static int __usb_suspend_device(struct usb_device *,
+			static int __usb_port_suspend(struct usb_device *,
 						int port1);
-			err = __usb_suspend_device(udev, udev->bus->otg_port);
+			err = __usb_port_suspend(udev, udev->bus->otg_port);
 			if (err < 0)
 				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
 		}
@@ -1418,34 +1300,15 @@
 	}
 #endif
 
-	/* put device-specific files into sysfs */
+	/* Register the device.  The device driver is responsible
+	 * for adding the device files to usbfs and sysfs and for
+	 * configuring the device.
+	 */
 	err = device_add (&udev->dev);
 	if (err) {
 		dev_err(&udev->dev, "can't device_add, error %d\n", err);
 		goto fail;
 	}
-	usb_create_sysfs_dev_files (udev);
-
-	usb_lock_device(udev);
-
-	/* choose and set the configuration. that registers the interfaces
-	 * with the driver core, and lets usb device drivers bind to them.
-	 */
-	c = choose_configuration(udev);
-	if (c >= 0) {
-		err = usb_set_configuration(udev, c);
-		if (err) {
-			dev_err(&udev->dev, "can't set config #%d, error %d\n",
-					c, err);
-			/* This need not be fatal.  The user can try to
-			 * set other configurations. */
-		}
-	}
-
-	/* USB device state == configured ... usable */
-	usb_notify_add_device(udev);
-
-	usb_unlock_device(udev);
 
 	return 0;
 
@@ -1472,6 +1335,18 @@
 	return ret;
 }
 
+
+/* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
+static unsigned hub_is_wusb(struct usb_hub *hub)
+{
+	struct usb_hcd *hcd;
+	if (hub->hdev->parent != NULL)  /* not a root hub? */
+		return 0;
+	hcd = container_of(hub->hdev->bus, struct usb_hcd, self);
+	return hcd->wireless;
+}
+
+
 #define PORT_RESET_TRIES	5
 #define SET_ADDRESS_TRIES	2
 #define GET_DESCRIPTOR_TRIES	2
@@ -1512,7 +1387,9 @@
 		/* if we`ve finished resetting, then break out of the loop */
 		if (!(portstatus & USB_PORT_STAT_RESET) &&
 		    (portstatus & USB_PORT_STAT_ENABLE)) {
-			if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+			if (hub_is_wusb(hub))
+				udev->speed = USB_SPEED_VARIABLE;
+			else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
 				udev->speed = USB_SPEED_HIGH;
 			else if (portstatus & USB_PORT_STAT_LOW_SPEED)
 				udev->speed = USB_SPEED_LOW;
@@ -1607,6 +1484,7 @@
  	kick_khubd(hub);
 }
 
+#ifdef	CONFIG_PM
 
 #ifdef	CONFIG_USB_SUSPEND
 
@@ -1633,7 +1511,7 @@
 	 * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
 	 * we don't explicitly enable it here.
 	 */
-	if (device_may_wakeup(&udev->dev)) {
+	if (udev->do_remote_wakeup) {
 		status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
 				USB_DEVICE_REMOTE_WAKEUP, 0,
@@ -1659,7 +1537,8 @@
 				USB_CTRL_SET_TIMEOUT);
 	} else {
 		/* device has up to 10 msec to fully suspend */
-		dev_dbg(&udev->dev, "usb suspend\n");
+		dev_dbg(&udev->dev, "usb %ssuspend\n",
+				udev->auto_pm ? "auto-" : "");
 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
 		msleep(10);
 	}
@@ -1684,7 +1563,7 @@
  * the root hub for their bus goes into global suspend ... so we don't
  * (falsely) update the device power state to say it suspended.
  */
-static int __usb_suspend_device (struct usb_device *udev, int port1)
+static int __usb_port_suspend (struct usb_device *udev, int port1)
 {
 	int	status = 0;
 
@@ -1692,49 +1571,29 @@
 	if (port1 < 0)
 		return port1;
 
-	if (udev->state == USB_STATE_SUSPENDED
-			|| udev->state == USB_STATE_NOTATTACHED) {
-		return 0;
-	}
-
-	/* all interfaces must already be suspended */
-	if (udev->actconfig) {
-		int	i;
-
-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-			struct usb_interface	*intf;
-
-			intf = udev->actconfig->interface[i];
-			if (is_active(intf)) {
-				dev_dbg(&intf->dev, "nyet suspended\n");
-				return -EBUSY;
-			}
-		}
-	}
-
-	/* we only change a device's upstream USB link.
-	 * root hubs have no upstream USB link.
+	/* we change the device's upstream USB link,
+	 * but root hubs have no upstream USB link.
 	 */
 	if (udev->parent)
 		status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
 				udev);
-
-	if (status == 0)
-		udev->dev.power.power_state = PMSG_SUSPEND;
+	else {
+		dev_dbg(&udev->dev, "usb %ssuspend\n",
+				udev->auto_pm ? "auto-" : "");
+		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+	}
 	return status;
 }
 
-#endif
-
 /*
- * usb_suspend_device - suspend a usb device
+ * usb_port_suspend - suspend a usb device's upstream port
  * @udev: device that's no longer in active use
  * Context: must be able to sleep; device not locked; pm locks held
  *
  * Suspends a USB device that isn't in active use, conserving power.
  * Devices may wake out of a suspend, if anything important happens,
  * using the remote wakeup mechanism.  They may also be taken out of
- * suspend by the host, using usb_resume_device().  It's also routine
+ * suspend by the host, using usb_port_resume().  It's also routine
  * to disconnect devices while they are suspended.
  *
  * This only affects the USB hardware for a device; its interfaces
@@ -1746,17 +1605,9 @@
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_suspend_device(struct usb_device *udev)
+int usb_port_suspend(struct usb_device *udev)
 {
-#ifdef	CONFIG_USB_SUSPEND
-	if (udev->state == USB_STATE_NOTATTACHED)
-		return -ENODEV;
-	return __usb_suspend_device(udev, udev->portnum);
-#else
-	/* NOTE:  udev->state unchanged, it's not lying ... */
-	udev->dev.power.power_state = PMSG_SUSPEND;
-	return 0;
-#endif
+	return __usb_port_suspend(udev, udev->portnum);
 }
 
 /*
@@ -1767,7 +1618,7 @@
  * resume (by host) or remote wakeup (by device) ... now see what changed
  * in the tree that's rooted at this device.
  */
-static int finish_device_resume(struct usb_device *udev)
+static int finish_port_resume(struct usb_device *udev)
 {
 	int	status;
 	u16	devstatus;
@@ -1783,7 +1634,6 @@
 	usb_set_device_state(udev, udev->actconfig
 			? USB_STATE_CONFIGURED
 			: USB_STATE_ADDRESS);
-	udev->dev.power.power_state = PMSG_ON;
 
  	/* 10.5.4.5 says be sure devices in the tree are still there.
  	 * For now let's assume the device didn't go crazy on resume,
@@ -1798,9 +1648,6 @@
 			"gone after usb resume? status %d\n",
 			status);
 	else if (udev->actconfig) {
-		unsigned	i;
-		int		(*resume)(struct device *);
-
 		le16_to_cpus(&devstatus);
 		if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
 				&& udev->parent) {
@@ -1811,24 +1658,9 @@
 					USB_DEVICE_REMOTE_WAKEUP, 0,
 					NULL, 0,
 					USB_CTRL_SET_TIMEOUT);
-			if (status) {
+			if (status)
 				dev_dbg(&udev->dev, "disable remote "
 					"wakeup, status %d\n", status);
-				status = 0;
-			}
-		}
-
-		/* resume interface drivers; if this is a hub, it
-		 * may have a child resume event to deal with soon
-		 */
-		resume = udev->dev.bus->resume;
-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-			struct device *dev =
-					&udev->actconfig->interface[i]->dev;
-
-			down(&dev->sem);
-			(void) resume(dev);
-			up(&dev->sem);
 		}
 		status = 0;
 
@@ -1839,8 +1671,6 @@
 	return status;
 }
 
-#ifdef	CONFIG_USB_SUSPEND
-
 static int
 hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 {
@@ -1848,6 +1678,8 @@
 
 	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
 
+	set_bit(port1, hub->busy_bits);
+
 	/* see 7.1.7.7; affects power usage, but not budgeting */
 	status = clear_port_feature(hub->hdev,
 			port1, USB_PORT_FEAT_SUSPEND);
@@ -1861,7 +1693,8 @@
 
 		/* drive resume for at least 20 msec */
 		if (udev)
-			dev_dbg(&udev->dev, "RESUME\n");
+			dev_dbg(&udev->dev, "usb %sresume\n",
+					udev->auto_pm ? "auto-" : "");
 		msleep(25);
 
 #define LIVE_FLAGS	( USB_PORT_STAT_POWER \
@@ -1891,19 +1724,21 @@
 			/* TRSMRCY = 10 msec */
 			msleep(10);
 			if (udev)
-				status = finish_device_resume(udev);
+				status = finish_port_resume(udev);
 		}
 	}
 	if (status < 0)
 		hub_port_logical_disconnect(hub, port1);
 
+	clear_bit(port1, hub->busy_bits);
+	if (!hub->hdev->parent && !hub->busy_bits[0])
+		usb_enable_root_hub_irq(hub->hdev->bus);
+
 	return status;
 }
 
-#endif
-
 /*
- * usb_resume_device - re-activate a suspended usb device
+ * usb_port_resume - re-activate a suspended usb device's upstream port
  * @udev: device to re-activate
  * Context: must be able to sleep; device not locked; pm locks held
  *
@@ -1915,36 +1750,24 @@
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_resume_device(struct usb_device *udev)
+int usb_port_resume(struct usb_device *udev)
 {
 	int	status;
 
-	if (udev->state == USB_STATE_NOTATTACHED)
-		return -ENODEV;
-
-	/* selective resume of one downstream hub-to-device port */
+	/* we change the device's upstream USB link,
+	 * but root hubs have no upstream USB link.
+	 */
 	if (udev->parent) {
-#ifdef	CONFIG_USB_SUSPEND
-		if (udev->state == USB_STATE_SUSPENDED) {
-			// NOTE swsusp may bork us, device state being wrong...
-			// NOTE this fails if parent is also suspended...
-			status = hub_port_resume(hdev_to_hub(udev->parent),
-					udev->portnum, udev);
-		} else
-#endif
-			status = 0;
-	} else
-		status = finish_device_resume(udev);
-	if (status < 0)
-		dev_dbg(&udev->dev, "can't resume, status %d\n",
-			status);
-
-	/* rebind drivers that had no suspend() */
-	if (status == 0) {
-		usb_unlock_device(udev);
-		bus_rescan_devices(&usb_bus_type);
-		usb_lock_device(udev);
+		// NOTE this fails if parent is also suspended...
+		status = hub_port_resume(hdev_to_hub(udev->parent),
+				udev->portnum, udev);
+	} else {
+		dev_dbg(&udev->dev, "usb %sresume\n",
+				udev->auto_pm ? "auto-" : "");
+		status = finish_port_resume(udev);
 	}
+	if (status < 0)
+		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
 	return status;
 }
 
@@ -1952,23 +1775,60 @@
 {
 	int	status = 0;
 
-#ifdef	CONFIG_USB_SUSPEND
+	/* All this just to avoid sending a port-resume message
+	 * to the parent hub! */
 
-	/* don't repeat RESUME sequence if this device
-	 * was already woken up by some other task
-	 */
 	usb_lock_device(udev);
+	usb_pm_lock(udev);
 	if (udev->state == USB_STATE_SUSPENDED) {
-		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
 		/* TRSMRCY = 10 msec */
 		msleep(10);
-		status = finish_device_resume(udev);
+		status = finish_port_resume(udev);
+		if (status == 0)
+			udev->dev.power.power_state.event = PM_EVENT_ON;
 	}
+	usb_pm_unlock(udev);
+
+	if (status == 0)
+		usb_autoresume_device(udev, 0);
 	usb_unlock_device(udev);
-#endif
 	return status;
 }
 
+#else	/* CONFIG_USB_SUSPEND */
+
+/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
+
+int usb_port_suspend(struct usb_device *udev)
+{
+	return 0;
+}
+
+static inline int
+finish_port_resume(struct usb_device *udev)
+{
+	return 0;
+}
+
+static inline int
+hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+{
+	return 0;
+}
+
+int usb_port_resume(struct usb_device *udev)
+{
+	return 0;
+}
+
+static inline int remote_wakeup(struct usb_device *udev)
+{
+	return 0;
+}
+
+#endif
+
 static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
 	struct usb_hub		*hub = usb_get_intfdata (intf);
@@ -1980,13 +1840,17 @@
 		struct usb_device	*udev;
 
 		udev = hdev->children [port1-1];
-		if (udev && (udev->dev.power.power_state.event
-					== PM_EVENT_ON
+		if (udev && msg.event == PM_EVENT_SUSPEND &&
 #ifdef	CONFIG_USB_SUSPEND
-				|| udev->state != USB_STATE_SUSPENDED
+				udev->state != USB_STATE_SUSPENDED
+#else
+				udev->dev.power.power_state.event
+					== PM_EVENT_ON
 #endif
-				)) {
-			dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
+				) {
+			if (!hdev->auto_pm)
+				dev_dbg(&intf->dev, "port %d nyet suspended\n",
+						port1);
 			return -EBUSY;
 		}
 	}
@@ -2035,66 +1899,22 @@
 		}
 	}
 
+	/* tell khubd to look for changes on this hub */
 	hub_activate(hub);
-
-	/* REVISIT:  this recursion probably shouldn't exist.  Remove
-	 * this code sometime, after retesting with different root and
-	 * external hubs.
-	 */
-#ifdef	CONFIG_USB_SUSPEND
-	{
-	unsigned		port1;
-
-	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
-		struct usb_device	*udev;
-		u16			portstat, portchange;
-
-		udev = hdev->children [port1-1];
-		status = hub_port_status(hub, port1, &portstat, &portchange);
-		if (status == 0) {
-			if (portchange & USB_PORT_STAT_C_SUSPEND) {
-				clear_port_feature(hdev, port1,
-					USB_PORT_FEAT_C_SUSPEND);
-				portchange &= ~USB_PORT_STAT_C_SUSPEND;
-			}
-
-			/* let khubd handle disconnects etc */
-			if (portchange)
-				continue;
-		}
-
-		if (!udev || status < 0)
-			continue;
-		usb_lock_device(udev);
-		if (portstat & USB_PORT_STAT_SUSPEND)
-			status = hub_port_resume(hub, port1, udev);
-		else {
-			status = finish_device_resume(udev);
-			if (status < 0) {
-				dev_dbg(&intf->dev, "resume port %d --> %d\n",
-					port1, status);
-				hub_port_logical_disconnect(hub, port1);
-			}
-		}
-		usb_unlock_device(udev);
-	}
-	}
-#endif
 	return 0;
 }
 
-void usb_suspend_root_hub(struct usb_device *hdev)
-{
-	struct usb_hub *hub = hdev_to_hub(hdev);
+#else	/* CONFIG_PM */
 
-	/* This also makes any led blinker stop retriggering.  We're called
-	 * from irq, so the blinker might still be scheduled.  Caller promises
-	 * that the root hub status URB will be canceled.
-	 */
-	__hub_quiesce(hub);
-	mark_quiesced(to_usb_interface(hub->intfdev));
+static inline int remote_wakeup(struct usb_device *udev)
+{
+	return 0;
 }
 
+#define hub_suspend NULL
+#define hub_resume NULL
+#endif
+
 void usb_resume_root_hub(struct usb_device *hdev)
 {
 	struct usb_hub *hub = hdev_to_hub(hdev);
@@ -2214,6 +2034,7 @@
 	int			i, j, retval;
 	unsigned		delay = HUB_SHORT_RESET_TIME;
 	enum usb_device_speed	oldspeed = udev->speed;
+	char 			*speed, *type;
 
 	/* root hub ports have a slightly longer reset period
 	 * (from USB 2.0 spec, section 7.1.7.5)
@@ -2246,8 +2067,13 @@
   
 	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
 	 * it's fixed size except for full speed devices.
+	 * For Wireless USB devices, ep0 max packet is always 512 (tho
+	 * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
 	 */
 	switch (udev->speed) {
+	case USB_SPEED_VARIABLE:	/* fixed at 512 */
+		udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512);
+		break;
 	case USB_SPEED_HIGH:		/* fixed at 64 */
 		udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
 		break;
@@ -2265,17 +2091,21 @@
 		goto fail;
 	}
  
+	type = "";
+	switch (udev->speed) {
+	case USB_SPEED_LOW:	speed = "low";	break;
+	case USB_SPEED_FULL:	speed = "full";	break;
+	case USB_SPEED_HIGH:	speed = "high";	break;
+	case USB_SPEED_VARIABLE:
+				speed = "variable";
+				type = "Wireless ";
+				break;
+	default: 		speed = "?";	break;
+	}
 	dev_info (&udev->dev,
-			"%s %s speed USB device using %s and address %d\n",
-			(udev->config) ? "reset" : "new",
-			({ char *speed; switch (udev->speed) {
-			case USB_SPEED_LOW:	speed = "low";	break;
-			case USB_SPEED_FULL:	speed = "full";	break;
-			case USB_SPEED_HIGH:	speed = "high";	break;
-			default: 		speed = "?";	break;
-			}; speed;}),
-			udev->bus->controller->driver->name,
-			udev->devnum);
+		  "%s %s speed %sUSB device using %s and address %d\n",
+		  (udev->config) ? "reset" : "new", speed, type,
+		  udev->bus->controller->driver->name, udev->devnum);
 
 	/* Set up TT records, if needed  */
 	if (hdev->tt) {
@@ -2317,6 +2147,8 @@
 			 * down tremendously by NAKing the unexpectedly
 			 * early status stage.  Also, retry on all errors;
 			 * some devices are flakey.
+			 * 255 is for WUSB devices, we actually need to use 512.
+			 * WUSB1.0[4.8.1].
 			 */
 			for (j = 0; j < 3; ++j) {
 				buf->bMaxPacketSize0 = 0;
@@ -2326,7 +2158,7 @@
 					buf, GET_DESCRIPTOR_BUFSIZE,
 					(i ? USB_CTRL_GET_TIMEOUT : 1000));
 				switch (buf->bMaxPacketSize0) {
-				case 8: case 16: case 32: case 64:
+				case 8: case 16: case 32: case 64: case 255:
 					if (buf->bDescriptorType ==
 							USB_DT_DEVICE) {
 						r = 0;
@@ -2400,7 +2232,8 @@
 	if (retval)
 		goto fail;
 
-	i = udev->descriptor.bMaxPacketSize0;
+	i = udev->descriptor.bMaxPacketSize0 == 0xff?
+	    512 : udev->descriptor.bMaxPacketSize0;
 	if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
 		if (udev->speed != USB_SPEED_FULL ||
 				!(i == 8 || i == 16 || i == 32 || i == 64)) {
@@ -2585,6 +2418,7 @@
 		usb_set_device_state(udev, USB_STATE_POWERED);
 		udev->speed = USB_SPEED_UNKNOWN;
  		udev->bus_mA = hub->mA_per_port;
+		udev->level = hdev->level + 1;
 
 		/* set the address */
 		choose_address(udev);
@@ -2736,17 +2570,6 @@
 		usb_get_intf(intf);
 		spin_unlock_irq(&hub_event_lock);
 
-		/* Is this is a root hub wanting to reactivate the downstream
-		 * ports?  If so, be sure the interface resumes even if its
-		 * stub "device" node was never suspended.
-		 */
-		if (i) {
-			dpm_runtime_resume(&hdev->dev);
-			dpm_runtime_resume(&intf->dev);
-			usb_put_intf(intf);
-			continue;
-		}
-
 		/* Lock the device, then check to see if we were
 		 * disconnected while waiting for the lock to succeed. */
 		if (locktree(hdev) < 0) {
@@ -2763,6 +2586,13 @@
 			goto loop;
 		}
 
+		/* Is this is a root hub wanting to reactivate the downstream
+		 * ports?  If so, be sure the interface resumes even if its
+		 * stub "device" node was never suspended.
+		 */
+		if (i)
+			usb_autoresume_device(hdev, 0);
+
 		/* If this is an inactive or suspended hub, do nothing */
 		if (hub->quiescing)
 			goto loop;
@@ -2900,7 +2730,7 @@
 
 		/* If this is a root hub, tell the HCD it's okay to
 		 * re-enable port-change interrupts now. */
-		if (!hdev->parent)
+		if (!hdev->parent && !hub->busy_bits[0])
 			usb_enable_root_hub_irq(hdev->bus);
 
 loop:
@@ -3075,6 +2905,9 @@
 			break;
 	}
 	clear_bit(port1, parent_hub->busy_bits);
+	if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+		usb_enable_root_hub_irq(parent_hdev->bus);
+
 	if (ret < 0)
 		goto re_enumerate;
  
@@ -3128,6 +2961,7 @@
 	hub_port_logical_disconnect(parent_hub, port1);
 	return -ENODEV;
 }
+EXPORT_SYMBOL(usb_reset_device);
 
 /**
  * usb_reset_composite_device - warn interface drivers and perform a USB port reset
@@ -3163,6 +2997,9 @@
 		return -EINVAL;
 	}
 
+	/* Prevent autosuspend during the reset */
+	usb_autoresume_device(udev, 1);
+
 	if (iface && iface->condition != USB_INTERFACE_BINDING)
 		iface = NULL;
 
@@ -3204,5 +3041,7 @@
 		}
 	}
 
+	usb_autosuspend_device(udev, 1);
 	return ret;
 }
+EXPORT_SYMBOL(usb_reset_composite_device);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 29d5f45..0f8e82a 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -212,7 +212,8 @@
 	unsigned long		event_bits[1];	/* status change bitmask */
 	unsigned long		change_bits[1];	/* ports with logical connect
 							status change */
-	unsigned long		busy_bits[1];	/* ports being reset */
+	unsigned long		busy_bits[1];	/* ports being reset or
+							resumed */
 #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
 #error event_bits[] is too short!
 #endif
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 58b4b10..df3d152 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -44,7 +44,7 @@
 #include "hcd.h"
 
 static struct super_operations usbfs_ops;
-static struct file_operations default_file_operations;
+static const struct file_operations default_file_operations;
 static struct vfsmount *usbfs_mount;
 static int usbfs_mount_count;	/* = 0 */
 static int ignore_mount = 0;
@@ -407,7 +407,7 @@
 	return 0;
 }
 
-static struct file_operations default_file_operations = {
+static const struct file_operations default_file_operations = {
 	.read =		default_read_file,
 	.write =	default_write_file,
 	.open =		default_open,
@@ -494,7 +494,7 @@
 
 static struct dentry *fs_create_file (const char *name, mode_t mode,
 				      struct dentry *parent, void *data,
-				      struct file_operations *fops,
+				      const struct file_operations *fops,
 				      uid_t uid, gid_t gid)
 {
 	struct dentry *dentry;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 4cc8d3e..85b1cd1 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -23,59 +23,44 @@
 }
 
 
-static void timeout_kill(unsigned long data)
-{
-	struct urb	*urb = (struct urb *) data;
-
-	usb_unlink_urb(urb);
-}
-
-// Starts urb and waits for completion or timeout
-// note that this call is NOT interruptible, while
-// many device driver i/o requests should be interruptible
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+/*
+ * Starts urb and waits for completion or timeout. Note that this call
+ * is NOT interruptible. Many device driver i/o requests should be
+ * interruptible and therefore these drivers should implement their
+ * own interruptible routines.
+ */
+static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
 { 
-	struct completion	done;
-	struct timer_list	timer;
-	int			status;
+	struct completion done;
+	unsigned long expire;
+	int status;
 
 	init_completion(&done); 	
 	urb->context = &done;
 	urb->actual_length = 0;
 	status = usb_submit_urb(urb, GFP_NOIO);
+	if (unlikely(status))
+		goto out;
 
-	if (status == 0) {
-		if (timeout > 0) {
-			init_timer(&timer);
-			timer.expires = jiffies + msecs_to_jiffies(timeout);
-			timer.data = (unsigned long)urb;
-			timer.function = timeout_kill;
-			/* grr.  timeout _should_ include submit delays. */
-			add_timer(&timer);
-		}
-		wait_for_completion(&done);
+	expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+	if (!wait_for_completion_timeout(&done, expire)) {
+
+		dev_dbg(&urb->dev->dev,
+			"%s timed out on ep%d%s len=%d/%d\n",
+			current->comm,
+			usb_pipeendpoint(urb->pipe),
+			usb_pipein(urb->pipe) ? "in" : "out",
+			urb->actual_length,
+			urb->transfer_buffer_length);
+
+		usb_kill_urb(urb);
+		status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
+	} else
 		status = urb->status;
-		/* note:  HCDs return ETIMEDOUT for other reasons too */
-		if (status == -ECONNRESET) {
-			dev_dbg(&urb->dev->dev,
-				"%s timed out on ep%d%s len=%d/%d\n",
-				current->comm,
-				usb_pipeendpoint(urb->pipe),
-				usb_pipein(urb->pipe) ? "in" : "out",
-				urb->actual_length,
-				urb->transfer_buffer_length
-				);
-			if (urb->actual_length > 0)
-				status = 0;
-			else
-				status = -ETIMEDOUT;
-		}
-		if (timeout > 0)
-			del_timer_sync(&timer);
-	}
-
+out:
 	if (actual_length)
 		*actual_length = urb->actual_length;
+
 	usb_free_urb(urb);
 	return status;
 }
@@ -263,7 +248,7 @@
 
 static void sg_complete (struct urb *urb, struct pt_regs *regs)
 {
-	struct usb_sg_request	*io = (struct usb_sg_request *) urb->context;
+	struct usb_sg_request	*io = urb->context;
 
 	spin_lock (&io->lock);
 
@@ -999,8 +984,8 @@
 		ep = dev->ep_in[epnum];
 		dev->ep_in[epnum] = NULL;
 	}
-	if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
-		dev->bus->op->disable(dev, ep);
+	if (ep && dev->bus)
+		usb_hcd_endpoint_disable(dev, ep);
 }
 
 /**
@@ -1381,9 +1366,6 @@
 	if (cp && configuration == 0)
 		dev_warn(&dev->dev, "config 0 descriptor??\n");
 
-	if (dev->state == USB_STATE_SUSPENDED)
-		return -EHOSTUNREACH;
-
 	/* Allocate memory for new interfaces before doing anything else,
 	 * so that if we run out then nothing will have changed. */
 	n = nintf = 0;
@@ -1418,6 +1400,11 @@
 					configuration, -i);
 	}
 
+	/* Wake up the device so we can send it the Set-Config request */
+	ret = usb_autoresume_device(dev, 1);
+	if (ret)
+		goto free_interfaces;
+
 	/* if it's already configured, clear out old state first.
 	 * getting rid of old interfaces means unbinding their drivers.
 	 */
@@ -1437,6 +1424,7 @@
 	dev->actconfig = cp;
 	if (!cp) {
 		usb_set_device_state(dev, USB_STATE_ADDRESS);
+		usb_autosuspend_device(dev, 1);
 		goto free_interfaces;
 	}
 	usb_set_device_state(dev, USB_STATE_CONFIGURED);
@@ -1505,9 +1493,69 @@
 		usb_create_sysfs_intf_files (intf);
 	}
 
+	usb_autosuspend_device(dev, 1);
 	return 0;
 }
 
+struct set_config_request {
+	struct usb_device	*udev;
+	int			config;
+	struct work_struct	work;
+};
+
+/* Worker routine for usb_driver_set_configuration() */
+static void driver_set_config_work(void *_req)
+{
+	struct set_config_request *req = _req;
+
+	usb_lock_device(req->udev);
+	usb_set_configuration(req->udev, req->config);
+	usb_unlock_device(req->udev);
+	usb_put_dev(req->udev);
+	kfree(req);
+}
+
+/**
+ * usb_driver_set_configuration - Provide a way for drivers to change device configurations
+ * @udev: the device whose configuration is being updated
+ * @config: the configuration being chosen.
+ * Context: In process context, must be able to sleep
+ *
+ * Device interface drivers are not allowed to change device configurations.
+ * This is because changing configurations will destroy the interface the
+ * driver is bound to and create new ones; it would be like a floppy-disk
+ * driver telling the computer to replace the floppy-disk drive with a
+ * tape drive!
+ *
+ * Still, in certain specialized circumstances the need may arise.  This
+ * routine gets around the normal restrictions by using a work thread to
+ * submit the change-config request.
+ *
+ * Returns 0 if the request was succesfully queued, error code otherwise.
+ * The caller has no way to know whether the queued request will eventually
+ * succeed.
+ */
+int usb_driver_set_configuration(struct usb_device *udev, int config)
+{
+	struct set_config_request *req;
+
+	req = kmalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+	req->udev = udev;
+	req->config = config;
+	INIT_WORK(&req->work, driver_set_config_work, req);
+
+	usb_get_dev(udev);
+	if (!schedule_work(&req->work)) {
+		usb_put_dev(udev);
+		kfree(req);
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
+
 // synchronous request completion model
 EXPORT_SYMBOL(usb_control_msg);
 EXPORT_SYMBOL(usb_bulk_msg);
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
index b042676..6b36897 100644
--- a/drivers/usb/core/notify.c
+++ b/drivers/usb/core/notify.c
@@ -50,8 +50,11 @@
 
 void usb_notify_remove_device(struct usb_device *udev)
 {
+	/* Protect against simultaneous usbfs open */
+	mutex_lock(&usbfs_mutex);
 	blocking_notifier_call_chain(&usb_notifier_list,
 			USB_DEVICE_REMOVE, udev);
+	mutex_unlock(&usbfs_mutex);
 }
 
 void usb_notify_add_bus(struct usb_bus *ubus)
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index dec973a..55d8f57 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -60,7 +60,7 @@
 set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct usb_device	*udev = udev = to_usb_device (dev);
+	struct usb_device	*udev = to_usb_device (dev);
 	int			config, value;
 
 	if (sscanf (buf, "%u", &config) != 1 || config > 255)
@@ -186,6 +186,7 @@
 
 static struct attribute *dev_attrs[] = {
 	/* current configuration's attributes */
+	&dev_attr_configuration.attr,
 	&dev_attr_bNumInterfaces.attr,
 	&dev_attr_bConfigurationValue.attr,
 	&dev_attr_bmAttributes.attr,
@@ -209,20 +210,40 @@
 	.attrs = dev_attrs,
 };
 
-void usb_create_sysfs_dev_files (struct usb_device *udev)
+int usb_create_sysfs_dev_files(struct usb_device *udev)
 {
 	struct device *dev = &udev->dev;
+	int retval;
 
-	sysfs_create_group(&dev->kobj, &dev_attr_grp);
+	retval = sysfs_create_group(&dev->kobj, &dev_attr_grp);
+	if (retval)
+		return retval;
 
-	if (udev->manufacturer)
-		device_create_file (dev, &dev_attr_manufacturer);
-	if (udev->product)
-		device_create_file (dev, &dev_attr_product);
-	if (udev->serial)
-		device_create_file (dev, &dev_attr_serial);
-	device_create_file (dev, &dev_attr_configuration);
-	usb_create_ep_files(dev, &udev->ep0, udev);
+	if (udev->manufacturer) {
+		retval = device_create_file (dev, &dev_attr_manufacturer);
+		if (retval)
+			goto error;
+	}
+	if (udev->product) {
+		retval = device_create_file (dev, &dev_attr_product);
+		if (retval)
+			goto error;
+	}
+	if (udev->serial) {
+		retval = device_create_file (dev, &dev_attr_serial);
+		if (retval)
+			goto error;
+	}
+	retval = usb_create_ep_files(dev, &udev->ep0, udev);
+	if (retval)
+		goto error;
+	return 0;
+error:
+	usb_remove_ep_files(&udev->ep0);
+	device_remove_file(dev, &dev_attr_manufacturer);
+	device_remove_file(dev, &dev_attr_product);
+	device_remove_file(dev, &dev_attr_serial);
+	return retval;
 }
 
 void usb_remove_sysfs_dev_files (struct usb_device *udev)
@@ -238,7 +259,6 @@
 		device_remove_file(dev, &dev_attr_product);
 	if (udev->serial)
 		device_remove_file(dev, &dev_attr_serial);
-	device_remove_file (dev, &dev_attr_configuration);
 }
 
 /* Interface fields */
@@ -340,18 +360,28 @@
 		usb_remove_ep_files(&iface_desc->endpoint[i]);
 }
 
-void usb_create_sysfs_intf_files (struct usb_interface *intf)
+int usb_create_sysfs_intf_files(struct usb_interface *intf)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct usb_host_interface *alt = intf->cur_altsetting;
+	int retval;
 
-	sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+	retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+	if (retval)
+		goto error;
 
 	if (alt->string == NULL)
 		alt->string = usb_cache_string(udev, alt->desc.iInterface);
 	if (alt->string)
-		device_create_file(&intf->dev, &dev_attr_interface);
+		retval = device_create_file(&intf->dev, &dev_attr_interface);
 	usb_create_intf_ep_files(intf, udev);
+	return 0;
+error:
+	if (alt->string)
+		device_remove_file(&intf->dev, &dev_attr_interface);
+	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
+	usb_remove_intf_ep_files(intf);
+	return retval;
 }
 
 void usb_remove_sysfs_intf_files (struct usb_interface *intf)
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 9864988..9801d08e 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -57,7 +57,7 @@
 {
 	struct urb *urb;
 
-	urb = (struct urb *)kmalloc(sizeof(struct urb) + 
+	urb = kmalloc(sizeof(struct urb) +
 		iso_packets * sizeof(struct usb_iso_packet_descriptor),
 		mem_flags);
 	if (!urb) {
@@ -221,7 +221,6 @@
 {
 	int			pipe, temp, max;
 	struct usb_device	*dev;
-	struct usb_operations	*op;
 	int			is_out;
 
 	if (!urb || urb->hcpriv || !urb->complete)
@@ -233,8 +232,6 @@
 	if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
 			|| dev->state == USB_STATE_SUSPENDED)
 		return -EHOSTUNREACH;
-	if (!(op = dev->bus->op) || !op->submit_urb)
-		return -ENODEV;
 
 	urb->status = -EINPROGRESS;
 	urb->actual_length = 0;
@@ -376,7 +373,7 @@
 		urb->interval = temp;
 	}
 
-	return op->submit_urb (urb, mem_flags);
+	return usb_hcd_submit_urb (urb, mem_flags);
 }
 
 /*-------------------------------------------------------------------*/
@@ -440,9 +437,9 @@
 {
 	if (!urb)
 		return -EINVAL;
-	if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
+	if (!(urb->dev && urb->dev->bus))
 		return -ENODEV;
-	return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
+	return usb_hcd_unlink_urb(urb, -ECONNRESET);
 }
 
 /**
@@ -468,13 +465,13 @@
 void usb_kill_urb(struct urb *urb)
 {
 	might_sleep();
-	if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
+	if (!(urb && urb->dev && urb->dev->bus))
 		return;
 	spin_lock_irq(&urb->lock);
 	++urb->reject;
 	spin_unlock_irq(&urb->lock);
 
-	urb->dev->bus->op->unlink_urb(urb, -ENOENT);
+	usb_hcd_unlink_urb(urb, -ENOENT);
 	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
 
 	spin_lock_irq(&urb->lock);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 184c246..e4df9ed 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -33,6 +33,7 @@
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include <asm/io.h>
 #include <asm/scatterlist.h>
@@ -47,6 +48,8 @@
 
 static int nousb;	/* Disable USB when built into kernel image */
 
+struct workqueue_struct *ksuspend_usb_wq;	/* For autosuspend */
+
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -67,7 +70,8 @@
  * Don't call this function unless you are bound to one of the interfaces
  * on this device or you have locked the device!
  */
-struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
+struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
+				      unsigned ifnum)
 {
 	struct usb_host_config *config = dev->actconfig;
 	int i;
@@ -100,8 +104,8 @@
  * Don't call this function unless you are bound to the intf interface
  * or you have locked the device!
  */
-struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
-		unsigned int altnum)
+struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf,
+						    unsigned int altnum)
 {
 	int i;
 
@@ -112,87 +116,6 @@
 	return NULL;
 }
 
-/**
- * usb_driver_claim_interface - bind a driver to an interface
- * @driver: the driver to be bound
- * @iface: the interface to which it will be bound; must be in the
- *	usb device's active configuration
- * @priv: driver data associated with that interface
- *
- * This is used by usb device drivers that need to claim more than one
- * interface on a device when probing (audio and acm are current examples).
- * No device driver should directly modify internal usb_interface or
- * usb_device structure members.
- *
- * Few drivers should need to use this routine, since the most natural
- * way to bind to an interface is to return the private data from
- * the driver's probe() method.
- *
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver probe() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
- */
-int usb_driver_claim_interface(struct usb_driver *driver,
-				struct usb_interface *iface, void* priv)
-{
-	struct device *dev = &iface->dev;
-
-	if (dev->driver)
-		return -EBUSY;
-
-	dev->driver = &driver->driver;
-	usb_set_intfdata(iface, priv);
-	iface->condition = USB_INTERFACE_BOUND;
-	mark_active(iface);
-
-	/* if interface was already added, bind now; else let
-	 * the future device_add() bind it, bypassing probe()
-	 */
-	if (device_is_registered(dev))
-		device_bind_driver(dev);
-
-	return 0;
-}
-
-/**
- * usb_driver_release_interface - unbind a driver from an interface
- * @driver: the driver to be unbound
- * @iface: the interface from which it will be unbound
- *
- * This can be used by drivers to release an interface without waiting
- * for their disconnect() methods to be called.  In typical cases this
- * also causes the driver disconnect() method to be called.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver disconnect() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
- */
-void usb_driver_release_interface(struct usb_driver *driver,
-					struct usb_interface *iface)
-{
-	struct device *dev = &iface->dev;
-
-	/* this should never happen, don't release something that's not ours */
-	if (!dev->driver || dev->driver != &driver->driver)
-		return;
-
-	/* don't release from within disconnect() */
-	if (iface->condition != USB_INTERFACE_BOUND)
-		return;
-
-	/* don't release if the interface hasn't been added yet */
-	if (device_is_registered(dev)) {
-		iface->condition = USB_INTERFACE_UNBINDING;
-		device_release_driver(dev);
-	}
-
-	dev->driver = NULL;
-	usb_set_intfdata(iface, NULL);
-	iface->condition = USB_INTERFACE_UNBOUND;
-	mark_quiesced(iface);
-}
-
 struct find_interface_arg {
 	int minor;
 	struct usb_interface *interface;
@@ -204,7 +127,7 @@
 	struct usb_interface *intf;
 
 	/* can't look at usb devices, only interfaces */
-	if (dev->driver == &usb_generic_driver)
+	if (is_usb_device(dev))
 		return 0;
 
 	intf = to_usb_interface(dev);
@@ -227,127 +150,16 @@
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
 	struct find_interface_arg argb;
+	int retval;
 
 	argb.minor = minor;
 	argb.interface = NULL;
-	driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
+	/* eat the error, it will be in argb.interface */
+	retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb,
+					__find_interface);
 	return argb.interface;
 }
 
-#ifdef	CONFIG_HOTPLUG
-
-/*
- * This sends an uevent to userspace, typically helping to load driver
- * or other modules, configure the device, and more.  Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- * We're called either from khubd (the typical case) or from root hub
- * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
- * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
- * device (and this configuration!) are still present.
- */
-static int usb_uevent(struct device *dev, char **envp, int num_envp,
-		      char *buffer, int buffer_size)
-{
-	struct usb_interface *intf;
-	struct usb_device *usb_dev;
-	struct usb_host_interface *alt;
-	int i = 0;
-	int length = 0;
-
-	if (!dev)
-		return -ENODEV;
-
-	/* driver is often null here; dev_dbg() would oops */
-	pr_debug ("usb %s: uevent\n", dev->bus_id);
-
-	/* Must check driver_data here, as on remove driver is always NULL */
-	if ((dev->driver == &usb_generic_driver) || 
-	    (dev->driver_data == &usb_generic_driver_data))
-		return 0;
-
-	intf = to_usb_interface(dev);
-	usb_dev = interface_to_usbdev (intf);
-	alt = intf->cur_altsetting;
-
-	if (usb_dev->devnum < 0) {
-		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
-		return -ENODEV;
-	}
-	if (!usb_dev->bus) {
-		pr_debug ("usb %s: bus removed?\n", dev->bus_id);
-		return -ENODEV;
-	}
-
-#ifdef	CONFIG_USB_DEVICEFS
-	/* If this is available, userspace programs can directly read
-	 * all the device descriptors we don't tell them about.  Or
-	 * even act as usermode drivers.
-	 *
-	 * FIXME reduce hardwired intelligence here
-	 */
-	if (add_uevent_var(envp, num_envp, &i,
-			   buffer, buffer_size, &length,
-			   "DEVICE=/proc/bus/usb/%03d/%03d",
-			   usb_dev->bus->busnum, usb_dev->devnum))
-		return -ENOMEM;
-#endif
-
-	/* per-device configurations are common */
-	if (add_uevent_var(envp, num_envp, &i,
-			   buffer, buffer_size, &length,
-			   "PRODUCT=%x/%x/%x",
-			   le16_to_cpu(usb_dev->descriptor.idVendor),
-			   le16_to_cpu(usb_dev->descriptor.idProduct),
-			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
-		return -ENOMEM;
-
-	/* class-based driver binding models */
-	if (add_uevent_var(envp, num_envp, &i,
-			   buffer, buffer_size, &length,
-			   "TYPE=%d/%d/%d",
-			   usb_dev->descriptor.bDeviceClass,
-			   usb_dev->descriptor.bDeviceSubClass,
-			   usb_dev->descriptor.bDeviceProtocol))
-		return -ENOMEM;
-
-	if (add_uevent_var(envp, num_envp, &i,
-			   buffer, buffer_size, &length,
-			   "INTERFACE=%d/%d/%d",
-			   alt->desc.bInterfaceClass,
-			   alt->desc.bInterfaceSubClass,
-			   alt->desc.bInterfaceProtocol))
-		return -ENOMEM;
-
-	if (add_uevent_var(envp, num_envp, &i,
-			   buffer, buffer_size, &length,
-			   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
-			   le16_to_cpu(usb_dev->descriptor.idVendor),
-			   le16_to_cpu(usb_dev->descriptor.idProduct),
-			   le16_to_cpu(usb_dev->descriptor.bcdDevice),
-			   usb_dev->descriptor.bDeviceClass,
-			   usb_dev->descriptor.bDeviceSubClass,
-			   usb_dev->descriptor.bDeviceProtocol,
-			   alt->desc.bInterfaceClass,
-			   alt->desc.bInterfaceSubClass,
-			   alt->desc.bInterfaceProtocol))
-		return -ENOMEM;
-
-	envp[i] = NULL;
-
-	return 0;
-}
-
-#else
-
-static int usb_uevent(struct device *dev, char **envp,
-			int num_envp, char *buffer, int buffer_size)
-{
-	return -ENODEV;
-}
-
-#endif	/* CONFIG_HOTPLUG */
-
 /**
  * usb_release_dev - free a usb device structure when all users of it are finished.
  * @dev: device that's been disconnected
@@ -361,14 +173,60 @@
 
 	udev = to_usb_device(dev);
 
+#ifdef	CONFIG_USB_SUSPEND
+	cancel_delayed_work(&udev->autosuspend);
+	flush_workqueue(ksuspend_usb_wq);
+#endif
 	usb_destroy_configuration(udev);
-	usb_bus_put(udev->bus);
+	usb_put_hcd(bus_to_hcd(udev->bus));
 	kfree(udev->product);
 	kfree(udev->manufacturer);
 	kfree(udev->serial);
 	kfree(udev);
 }
 
+#ifdef	CONFIG_PM
+
+static int ksuspend_usb_init(void)
+{
+	ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
+	if (!ksuspend_usb_wq)
+		return -ENOMEM;
+	return 0;
+}
+
+static void ksuspend_usb_cleanup(void)
+{
+	destroy_workqueue(ksuspend_usb_wq);
+}
+
+#else
+
+#define ksuspend_usb_init()	0
+#define ksuspend_usb_cleanup()	do {} while (0)
+
+#endif
+
+#ifdef	CONFIG_USB_SUSPEND
+
+/* usb_autosuspend_work - callback routine to autosuspend a USB device */
+static void usb_autosuspend_work(void *_udev)
+{
+	struct usb_device	*udev = _udev;
+
+	usb_pm_lock(udev);
+	udev->auto_pm = 1;
+	usb_suspend_both(udev, PMSG_SUSPEND);
+	usb_pm_unlock(udev);
+}
+
+#else
+
+static void usb_autosuspend_work(void *_udev)
+{}
+
+#endif
+
 /**
  * usb_alloc_dev - usb device constructor (usbcore-internal)
  * @parent: hub to which device is connected; null to allocate a root hub
@@ -390,8 +248,7 @@
 	if (!dev)
 		return NULL;
 
-	bus = usb_bus_get(bus);
-	if (!bus) {
+	if (!usb_get_hcd(bus_to_hcd(bus))) {
 		kfree(dev);
 		return NULL;
 	}
@@ -399,11 +256,12 @@
 	device_initialize(&dev->dev);
 	dev->dev.bus = &usb_bus_type;
 	dev->dev.dma_mask = bus->controller->dma_mask;
-	dev->dev.driver_data = &usb_generic_driver_data;
-	dev->dev.driver = &usb_generic_driver;
 	dev->dev.release = usb_release_dev;
 	dev->state = USB_STATE_ATTACHED;
 
+	/* This magic assignment distinguishes devices from interfaces */
+	dev->dev.platform_data = &usb_generic_driver;
+
 	INIT_LIST_HEAD(&dev->ep0.urb_list);
 	dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
 	dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
@@ -444,6 +302,10 @@
 	dev->parent = parent;
 	INIT_LIST_HEAD(&dev->filelist);
 
+#ifdef	CONFIG_PM
+	mutex_init(&dev->pm_mutex);
+	INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev);
+#endif
 	return dev;
 }
 
@@ -549,7 +411,7 @@
  * case the driver already owns the device lock.)
  */
 int usb_lock_device_for_reset(struct usb_device *udev,
-		struct usb_interface *iface)
+			      const struct usb_interface *iface)
 {
 	unsigned long jiffies_expire = jiffies + HZ;
 
@@ -672,7 +534,139 @@
  */
 int usb_get_current_frame_number(struct usb_device *dev)
 {
-	return dev->bus->op->get_frame_number (dev);
+	return usb_hcd_get_frame_number (dev);
+}
+
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
+{
+	return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
+{
+	return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
 }
 
 /*-------------------------------------------------------------------*/
@@ -737,9 +731,9 @@
 	dma_addr_t *dma
 )
 {
-	if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc)
+	if (!dev || !dev->bus)
 		return NULL;
-	return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma);
+	return hcd_buffer_alloc (dev->bus, size, mem_flags, dma);
 }
 
 /**
@@ -760,9 +754,11 @@
 	dma_addr_t dma
 )
 {
-	if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free)
-	    	return;
-	dev->bus->op->buffer_free (dev->bus, size, addr, dma);
+	if (!dev || !dev->bus)
+		return;
+	if (!addr)
+		return;
+	hcd_buffer_free (dev->bus, size, addr, dma);
 }
 
 /**
@@ -911,8 +907,8 @@
  *
  * Reverse the effect of this call with usb_buffer_unmap_sg().
  */
-int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
-		struct scatterlist *sg, int nents)
+int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+		      struct scatterlist *sg, int nents)
 {
 	struct usb_bus		*bus;
 	struct device		*controller;
@@ -946,8 +942,8 @@
  * Use this when you are re-using a scatterlist's data buffers for
  * another USB request.
  */
-void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
-		struct scatterlist *sg, int n_hw_ents)
+void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
+			   struct scatterlist *sg, int n_hw_ents)
 {
 	struct usb_bus		*bus;
 	struct device		*controller;
@@ -972,8 +968,8 @@
  *
  * Reverses the effect of usb_buffer_map_sg().
  */
-void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
-		struct scatterlist *sg, int n_hw_ents)
+void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
+			 struct scatterlist *sg, int n_hw_ents)
 {
 	struct usb_bus		*bus;
 	struct device		*controller;
@@ -988,116 +984,6 @@
 			usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 
-static int verify_suspended(struct device *dev, void *unused)
-{
-	if (dev->driver == NULL)
-		return 0;
-	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
-}
-
-static int usb_generic_suspend(struct device *dev, pm_message_t message)
-{
-	struct usb_interface	*intf;
-	struct usb_driver	*driver;
-	int			status;
-
-	/* USB devices enter SUSPEND state through their hubs, but can be
-	 * marked for FREEZE as soon as their children are already idled.
-	 * But those semantics are useless, so we equate the two (sigh).
-	 */
-	if (dev->driver == &usb_generic_driver) {
-		if (dev->power.power_state.event == message.event)
-			return 0;
-		/* we need to rule out bogus requests through sysfs */
-		status = device_for_each_child(dev, NULL, verify_suspended);
-		if (status)
-			return status;
- 		return usb_suspend_device (to_usb_device(dev));
-	}
-
-	if ((dev->driver == NULL) ||
-	    (dev->driver_data == &usb_generic_driver_data))
-		return 0;
-
-	intf = to_usb_interface(dev);
-	driver = to_usb_driver(dev->driver);
-
-	/* with no hardware, USB interfaces only use FREEZE and ON states */
-	if (!is_active(intf))
-		return 0;
-
-	if (driver->suspend && driver->resume) {
-		status = driver->suspend(intf, message);
-		if (status)
-			dev_err(dev, "%s error %d\n", "suspend", status);
-		else
-			mark_quiesced(intf);
-	} else {
-		// FIXME else if there's no suspend method, disconnect...
-		dev_warn(dev, "no suspend for driver %s?\n", driver->name);
-		mark_quiesced(intf);
-		status = 0;
-	}
-	return status;
-}
-
-static int usb_generic_resume(struct device *dev)
-{
-	struct usb_interface	*intf;
-	struct usb_driver	*driver;
-	struct usb_device	*udev;
-	int			status;
-
-	if (dev->power.power_state.event == PM_EVENT_ON)
-		return 0;
-
-	/* mark things as "on" immediately, no matter what errors crop up */
-	dev->power.power_state.event = PM_EVENT_ON;
-
-	/* devices resume through their hubs */
-	if (dev->driver == &usb_generic_driver) {
-		udev = to_usb_device(dev);
-		if (udev->state == USB_STATE_NOTATTACHED)
-			return 0;
-		return usb_resume_device (to_usb_device(dev));
-	}
-
-	if ((dev->driver == NULL) ||
-	    (dev->driver_data == &usb_generic_driver_data)) {
-		dev->power.power_state.event = PM_EVENT_FREEZE;
-		return 0;
-	}
-
-	intf = to_usb_interface(dev);
-	driver = to_usb_driver(dev->driver);
-
-	udev = interface_to_usbdev(intf);
-	if (udev->state == USB_STATE_NOTATTACHED)
-		return 0;
-
-	/* if driver was suspended, it has a resume method;
-	 * however, sysfs can wrongly mark things as suspended
-	 * (on the "no suspend method" FIXME path above)
-	 */
-	if (driver->resume) {
-		status = driver->resume(intf);
-		if (status) {
-			dev_err(dev, "%s error %d\n", "resume", status);
-			mark_quiesced(intf);
-		}
-	} else
-		dev_warn(dev, "no resume for driver %s?\n", driver->name);
-	return 0;
-}
-
-struct bus_type usb_bus_type = {
-	.name =		"usb",
-	.match =	usb_device_match,
-	.uevent =	usb_uevent,
-	.suspend =	usb_generic_suspend,
-	.resume =	usb_generic_resume,
-};
-
 /* format to disable USB on kernel command line is: nousb */
 __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
 
@@ -1120,9 +1006,12 @@
 		return 0;
 	}
 
+	retval = ksuspend_usb_init();
+	if (retval)
+		goto out;
 	retval = bus_register(&usb_bus_type);
 	if (retval) 
-		goto out;
+		goto bus_register_failed;
 	retval = usb_host_init();
 	if (retval)
 		goto host_init_failed;
@@ -1141,7 +1030,7 @@
 	retval = usb_hub_init();
 	if (retval)
 		goto hub_init_failed;
-	retval = driver_register(&usb_generic_driver);
+	retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
 	if (!retval)
 		goto out;
 
@@ -1158,6 +1047,8 @@
 	usb_host_cleanup();
 host_init_failed:
 	bus_unregister(&usb_bus_type);
+bus_register_failed:
+	ksuspend_usb_cleanup();
 out:
 	return retval;
 }
@@ -1171,7 +1062,7 @@
 	if (nousb)
 		return;
 
-	driver_unregister(&usb_generic_driver);
+	usb_deregister_device_driver(&usb_generic_driver);
 	usb_major_cleanup();
 	usbfs_cleanup();
 	usb_deregister(&usbfs_driver);
@@ -1179,6 +1070,7 @@
 	usb_hub_cleanup();
 	usb_host_cleanup();
 	bus_unregister(&usb_bus_type);
+	ksuspend_usb_cleanup();
 }
 
 subsys_initcall(usb_init);
@@ -1201,20 +1093,27 @@
 
 EXPORT_SYMBOL(usb_lock_device_for_reset);
 
-EXPORT_SYMBOL(usb_driver_claim_interface);
-EXPORT_SYMBOL(usb_driver_release_interface);
 EXPORT_SYMBOL(usb_find_interface);
 EXPORT_SYMBOL(usb_ifnum_to_if);
 EXPORT_SYMBOL(usb_altnum_to_altsetting);
 
-EXPORT_SYMBOL(usb_reset_device);
-EXPORT_SYMBOL(usb_reset_composite_device);
-
 EXPORT_SYMBOL(__usb_get_extra_descriptor);
 
 EXPORT_SYMBOL(usb_find_device);
 EXPORT_SYMBOL(usb_get_current_frame_number);
 
+EXPORT_SYMBOL_GPL(usb_endpoint_dir_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_dir_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out);
+
 EXPORT_SYMBOL (usb_buffer_alloc);
 EXPORT_SYMBOL (usb_buffer_free);
 
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 49f6923..f69df13 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -1,10 +1,10 @@
 /* Functions local to drivers/usb/core/ */
 
-extern void usb_create_sysfs_dev_files (struct usb_device *dev);
+extern int usb_create_sysfs_dev_files (struct usb_device *dev);
 extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
-extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
+extern int usb_create_sysfs_intf_files (struct usb_interface *intf);
 extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
+extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
 				struct usb_device *udev);
 extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
 
@@ -20,7 +20,6 @@
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_kick_khubd(struct usb_device *dev);
-extern void usb_suspend_root_hub(struct usb_device *hdev);
 extern void usb_resume_root_hub(struct usb_device *dev);
 
 extern int  usb_hub_init(void);
@@ -30,28 +29,91 @@
 extern int usb_host_init(void);
 extern void usb_host_cleanup(void);
 
-extern int usb_suspend_device(struct usb_device *dev);
-extern int usb_resume_device(struct usb_device *dev);
+#ifdef	CONFIG_PM
 
-extern struct device_driver usb_generic_driver;
-extern int usb_generic_driver_data;
-extern int usb_device_match(struct device *dev, struct device_driver *drv);
+extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg);
+extern int usb_resume_both(struct usb_device *udev);
+extern int usb_port_suspend(struct usb_device *dev);
+extern int usb_port_resume(struct usb_device *dev);
+
+static inline void usb_pm_lock(struct usb_device *udev)
+{
+	mutex_lock_nested(&udev->pm_mutex, udev->level);
+}
+
+static inline void usb_pm_unlock(struct usb_device *udev)
+{
+	mutex_unlock(&udev->pm_mutex);
+}
+
+#else
+
+#define usb_suspend_both(udev, msg)	0
+static inline int usb_resume_both(struct usb_device *udev)
+{
+	return 0;
+}
+#define usb_port_suspend(dev)		0
+#define usb_port_resume(dev)		0
+static inline void usb_pm_lock(struct usb_device *udev) {}
+static inline void usb_pm_unlock(struct usb_device *udev) {}
+
+#endif
+
+#ifdef CONFIG_USB_SUSPEND
+
+#define USB_AUTOSUSPEND_DELAY	(HZ*2)
+
+extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
+extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+
+#else
+
+#define usb_autosuspend_device(udev, dec_busy_cnt)	do {} while (0)
+static inline int usb_autoresume_device(struct usb_device *udev,
+		int inc_busy_cnt)
+{
+	return 0;
+}
+
+#endif
+
+extern struct workqueue_struct *ksuspend_usb_wq;
+extern struct bus_type usb_bus_type;
+extern struct usb_device_driver usb_generic_driver;
+
+/* Here's how we tell apart devices and interfaces.  Luckily there's
+ * no such thing as a platform USB device, so we can steal the use
+ * of the platform_data field. */
+
+static inline int is_usb_device(const struct device *dev)
+{
+	return dev->platform_data == &usb_generic_driver;
+}
+
+/* Do the same for device drivers and interface drivers. */
+
+static inline int is_usb_device_driver(struct device_driver *drv)
+{
+	return container_of(drv, struct usbdrv_wrap, driver)->
+			for_devices;
+}
 
 /* Interfaces and their "power state" are owned by usbcore */
 
 static inline void mark_active(struct usb_interface *f)
 {
-	f->dev.power.power_state.event = PM_EVENT_ON;
+	f->is_active = 1;
 }
 
 static inline void mark_quiesced(struct usb_interface *f)
 {
-	f->dev.power.power_state.event = PM_EVENT_FREEZE;
+	f->is_active = 0;
 }
 
-static inline int is_active(struct usb_interface *f)
+static inline int is_active(const struct usb_interface *f)
 {
-	return f->dev.power.power_state.event == PM_EVENT_ON;
+	return f->is_active;
 }
 
 
@@ -59,9 +121,10 @@
 extern const char *usbcore_name;
 
 /* usbfs stuff */
+extern struct mutex usbfs_mutex;
 extern struct usb_driver usbfs_driver;
-extern struct file_operations usbfs_devices_fops;
-extern struct file_operations usbfs_device_file_operations;
+extern const struct file_operations usbfs_devices_fops;
+extern const struct file_operations usbfs_device_file_operations;
 extern void usbfs_conn_disc_event(void);
 
 extern int usbdev_init(void);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 1a32d96..8e5dd6f 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -26,7 +26,7 @@
 	   you need a low level bus controller driver, and some software
 	   talking to it.  Peripheral controllers are often discrete silicon,
 	   or are integrated with the CPU in a microcontroller.  The more
-	   familiar host side controllers have names like like "EHCI", "OHCI",
+	   familiar host side controllers have names like "EHCI", "OHCI",
 	   or "UHCI", and are usually integrated into southbridges on PC
 	   motherboards.
 
@@ -404,6 +404,20 @@
 	  which includes instructions and a "driver info file" needed to
 	  make MS-Windows work with this driver.
 
+config USB_MIDI_GADGET
+	tristate "MIDI Gadget (EXPERIMENTAL)"
+	depends on SND && EXPERIMENTAL
+	select SND_RAWMIDI
+	help
+	  The MIDI Gadget acts as a USB Audio device, with one MIDI
+	  input and one MIDI output. These MIDI jacks appear as
+	  a sound "card" in the ALSA sound system. Other MIDI
+	  connections can then be made on the gadget system, using
+	  ALSA's aconnect utility etc.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_midi".
+
 
 # put drivers that need isochronous transfer support (for audio
 # or video class gadget drivers), or specific hardware, here.
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 5a28e613..e71e086 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -15,6 +15,7 @@
 g_zero-objs			:= zero.o usbstring.o config.o epautoconf.o
 g_ether-objs			:= ether.o usbstring.o config.o epautoconf.o
 g_serial-objs			:= serial.o usbstring.o config.o epautoconf.o
+g_midi-objs			:= gmidi.o usbstring.o config.o epautoconf.o
 gadgetfs-objs			:= inode.o
 g_file_storage-objs		:= file_storage.o usbstring.o config.o \
 					epautoconf.o
@@ -28,4 +29,5 @@
 obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
 obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
+obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
 
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index cfebca0..77beba4 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -247,7 +247,7 @@
 	return single_open(file, proc_udc_show, PDE(inode)->data);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
 	.open		= proc_udc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -1658,7 +1658,7 @@
 		return -ENODEV;
 	}
 
-	if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) {
+	if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) {
 		DBG("someone's using UDC memory\n");
 		return -EBUSY;
 	}
@@ -1720,7 +1720,7 @@
 fail1:
 	device_unregister(&udc->gadget.dev);
 fail0:
-	release_mem_region(AT91_BASE_UDP, SZ_16K);
+	release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
 	DBG("%s probe failed, %d\n", driver_name, retval);
 	return retval;
 }
@@ -1742,7 +1742,7 @@
 		free_irq(udc->board.vbus_pin, udc);
 	free_irq(udc->udp_irq, udc);
 	device_unregister(&udc->gadget.dev);
-	release_mem_region(AT91_BASE_UDP, SZ_16K);
+	release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
 
 	clk_put(udc->iclk);
 	clk_put(udc->fclk);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 7d1c22c..4d2946e 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -816,15 +816,14 @@
 	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
-	if ((retval = driver->bind (&dum->gadget)) != 0) {
-		dum->driver = NULL;
-		dum->gadget.dev.driver = NULL;
-		return retval;
-	}
+	if ((retval = driver->bind (&dum->gadget)) != 0)
+		goto err_bind_gadget;
 
 	driver->driver.bus = dum->gadget.dev.parent->bus;
-	driver_register (&driver->driver);
-	device_bind_driver (&dum->gadget.dev);
+	if ((retval = driver_register (&driver->driver)) != 0)
+		goto err_register;
+	if ((retval = device_bind_driver (&dum->gadget.dev)) != 0)
+		goto err_bind_driver;
 
 	/* khubd will enumerate this in a while */
 	spin_lock_irq (&dum->lock);
@@ -834,6 +833,19 @@
 
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
+
+err_bind_driver:
+	driver_unregister (&driver->driver);
+err_register:
+	driver->unbind (&dum->gadget);
+	spin_lock_irq (&dum->lock);
+	dum->pullup = 0;
+	set_link_state (dum);
+	spin_unlock_irq (&dum->lock);
+err_bind_gadget:
+	dum->driver = NULL;
+	dum->gadget.dev.driver = NULL;
+	return retval;
 }
 EXPORT_SYMBOL (usb_gadget_register_driver);
 
@@ -889,11 +901,9 @@
 static void
 dummy_gadget_release (struct device *dev)
 {
-#if 0		/* usb_bus_put isn't EXPORTed! */
 	struct dummy	*dum = gadget_dev_to_dummy (dev);
 
-	usb_bus_put (&dummy_to_hcd (dum)->self);
-#endif
+	usb_put_hcd (dummy_to_hcd (dum));
 }
 
 static int dummy_udc_probe (struct platform_device *pdev)
@@ -915,12 +925,12 @@
 	if (rc < 0)
 		return rc;
 
-#if 0		/* usb_bus_get isn't EXPORTed! */
-	usb_bus_get (&dummy_to_hcd (dum)->self);
-#endif
+	usb_get_hcd (dummy_to_hcd (dum));
 
 	platform_set_drvdata (pdev, dum);
-	device_create_file (&dum->gadget.dev, &dev_attr_function);
+	rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
+	if (rc < 0)
+		device_unregister (&dum->gadget.dev);
 	return rc;
 }
 
@@ -1868,8 +1878,7 @@
 #endif
 
 	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
-	device_create_file (dummy_dev(dum), &dev_attr_urbs);
-	return 0;
+	return device_create_file (dummy_dev(dum), &dev_attr_urbs);
 }
 
 static void dummy_stop (struct usb_hcd *hcd)
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 30299c6..366dc0a 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -262,7 +262,7 @@
 #define DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_MUSBHDRC
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 #define DEV_CONFIG_CDC
 #endif
 
@@ -2014,7 +2014,7 @@
 static int rndis_control_ack (struct net_device *net)
 {
 	struct eth_dev          *dev = netdev_priv(net);
-	u32                     length;
+	int                     length;
 	struct usb_request      *resp = dev->stat_req;
 
 	/* in case RNDIS calls this after disconnect */
@@ -2230,6 +2230,9 @@
 	if (gadget_is_pxa (gadget)) {
 		/* pxa doesn't support altsettings */
 		cdc = 0;
+	} else if (gadget_is_musbhdrc(gadget)) {
+		/* reduce tx dma overhead by avoiding special cases */
+		zlp = 0;
 	} else if (gadget_is_sh(gadget)) {
 		/* sh doesn't support multiple interfaces or configs */
 		cdc = 0;
@@ -2564,7 +2567,7 @@
 
 	.function	= (char *) driver_desc,
 	.bind		= eth_bind,
-	.unbind		= __exit_p(eth_unbind),
+	.unbind		= eth_unbind,
 
 	.setup		= eth_setup,
 	.disconnect	= eth_disconnect,
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 8d7f1e8..c83d3b6 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -567,6 +567,7 @@
 	unsigned int	ro : 1;
 	unsigned int	prevent_medium_removal : 1;
 	unsigned int	registered : 1;
+	unsigned int	info_valid : 1;
 
 	u32		sense_data;
 	u32		sense_data_info;
@@ -1656,6 +1657,7 @@
 			curlun->sense_data =
 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
 			curlun->sense_data_info = file_offset >> 9;
+			curlun->info_valid = 1;
 			bh->inreq->length = 0;
 			bh->state = BUF_STATE_FULL;
 			break;
@@ -1691,6 +1693,7 @@
 		if (nread < amount) {
 			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
 			curlun->sense_data_info = file_offset >> 9;
+			curlun->info_valid = 1;
 			break;
 		}
 
@@ -1785,6 +1788,7 @@
 				curlun->sense_data =
 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
 				curlun->sense_data_info = usb_offset >> 9;
+				curlun->info_valid = 1;
 				continue;
 			}
 			amount -= (amount & 511);
@@ -1827,6 +1831,7 @@
 			if (bh->outreq->status != 0) {
 				curlun->sense_data = SS_COMMUNICATION_FAILURE;
 				curlun->sense_data_info = file_offset >> 9;
+				curlun->info_valid = 1;
 				break;
 			}
 
@@ -1868,6 +1873,7 @@
 			if (nwritten < amount) {
 				curlun->sense_data = SS_WRITE_ERROR;
 				curlun->sense_data_info = file_offset >> 9;
+				curlun->info_valid = 1;
 				break;
 			}
 
@@ -2010,6 +2016,7 @@
 			curlun->sense_data =
 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
 			curlun->sense_data_info = file_offset >> 9;
+			curlun->info_valid = 1;
 			break;
 		}
 
@@ -2036,6 +2043,7 @@
 		if (nread == 0) {
 			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
 			curlun->sense_data_info = file_offset >> 9;
+			curlun->info_valid = 1;
 			break;
 		}
 		file_offset += nread;
@@ -2079,6 +2087,7 @@
 	struct lun	*curlun = fsg->curlun;
 	u8		*buf = (u8 *) bh->buf;
 	u32		sd, sdinfo;
+	int		valid;
 
 	/*
 	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
@@ -2106,15 +2115,18 @@
 		fsg->bad_lun_okay = 1;
 		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
 		sdinfo = 0;
+		valid = 0;
 	} else {
 		sd = curlun->sense_data;
 		sdinfo = curlun->sense_data_info;
+		valid = curlun->info_valid << 7;
 		curlun->sense_data = SS_NO_SENSE;
 		curlun->sense_data_info = 0;
+		curlun->info_valid = 0;
 	}
 
 	memset(buf, 0, 18);
-	buf[0] = 0x80 | 0x70;			// Valid, current error
+	buf[0] = valid | 0x70;			// Valid, current error
 	buf[2] = SK(sd);
 	put_be32(&buf[3], sdinfo);		// Sense information
 	buf[7] = 18 - 8;			// Additional sense length
@@ -2703,6 +2715,7 @@
 		if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->sense_data_info = 0;
+			curlun->info_valid = 0;
 		}
 	} else {
 		fsg->curlun = curlun = NULL;
@@ -3332,6 +3345,7 @@
 			curlun->sense_data = curlun->unit_attention_data =
 					SS_NO_SENSE;
 			curlun->sense_data_info = 0;
+			curlun->info_valid = 0;
 		}
 		fsg->state = FSG_STATE_IDLE;
 	}
@@ -3873,21 +3887,26 @@
 	for (i = 0; i < fsg->nluns; ++i) {
 		curlun = &fsg->luns[i];
 		curlun->ro = mod_data.ro[i];
+		curlun->dev.release = lun_release;
 		curlun->dev.parent = &gadget->dev;
 		curlun->dev.driver = &fsg_driver.driver;
 		dev_set_drvdata(&curlun->dev, fsg);
 		snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
 				"%s-lun%d", gadget->dev.bus_id, i);
 
-		if ((rc = device_register(&curlun->dev)) != 0)
+		if ((rc = device_register(&curlun->dev)) != 0) {
 			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-		else {
-			curlun->registered = 1;
-			curlun->dev.release = lun_release;
-			device_create_file(&curlun->dev, &dev_attr_ro);
-			device_create_file(&curlun->dev, &dev_attr_file);
-			kref_get(&fsg->ref);
+			goto out;
 		}
+		if ((rc = device_create_file(&curlun->dev,
+					&dev_attr_ro)) != 0 ||
+				(rc = device_create_file(&curlun->dev,
+					&dev_attr_file)) != 0) {
+			device_unregister(&curlun->dev);
+			goto out;
+		}
+		curlun->registered = 1;
+		kref_get(&fsg->ref);
 
 		if (mod_data.file[i] && *mod_data.file[i]) {
 			if ((rc = open_backing_file(curlun,
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
new file mode 100644
index 0000000..b68cecd
--- /dev/null
+++ b/drivers/usb/gadget/gmidi.c
@@ -0,0 +1,1337 @@
+/*
+ * gmidi.c -- USB MIDI Gadget Driver
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This code is based in part on:
+ *
+ * Gadget Zero driver, Copyright (C) 2003-2004 David Brownell.
+ * USB Audio driver, Copyright (C) 2002 by Takashi Iwai.
+ * USB MIDI driver, Copyright (C) 2002-2005 Clemens Ladisch.
+ *
+ * Refer to the USB Device Class Definition for MIDI Devices:
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ */
+
+#define DEBUG 1
+// #define VERBOSE
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/midi.h>
+
+#include "gadget_chips.h"
+
+MODULE_AUTHOR("Ben Williamson");
+MODULE_LICENSE("GPL v2");
+
+#define DRIVER_VERSION "25 Jul 2006"
+
+static const char shortname[] = "g_midi";
+static const char longname[] = "MIDI Gadget";
+
+static int index = SNDRV_DEFAULT_IDX1;
+static char *id = SNDRV_DEFAULT_STR1;
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter.");
+
+/* Some systems will want different product identifers published in the
+ * device descriptor, either numbers or strings or both.  These string
+ * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort idVendor;
+module_param(idVendor, ushort, S_IRUGO);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort idProduct;
+module_param(idProduct, ushort, S_IRUGO);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort bcdDevice;
+module_param(bcdDevice, ushort, S_IRUGO);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *iManufacturer;
+module_param(iManufacturer, charp, S_IRUGO);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *iProduct;
+module_param(iProduct, charp, S_IRUGO);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, S_IRUGO);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber");
+
+/*
+ * this version autoconfigures as much as possible,
+ * which is reasonable for most "bulk-only" drivers.
+ */
+static const char *EP_IN_NAME;
+static const char *EP_OUT_NAME;
+
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+/* This is a gadget, and the IN/OUT naming is from the host's perspective.
+   USB -> OUT endpoint -> rawmidi
+   USB <- IN endpoint  <- rawmidi */
+struct gmidi_in_port {
+	struct gmidi_device* dev;
+	int active;
+	uint8_t cable;		/* cable number << 4 */
+	uint8_t state;
+#define STATE_UNKNOWN	0
+#define STATE_1PARAM	1
+#define STATE_2PARAM_1	2
+#define STATE_2PARAM_2	3
+#define STATE_SYSEX_0	4
+#define STATE_SYSEX_1	5
+#define STATE_SYSEX_2	6
+	uint8_t data[2];
+};
+
+struct gmidi_device {
+	spinlock_t		lock;
+	struct usb_gadget	*gadget;
+	struct usb_request	*req;		/* for control responses */
+	u8			config;
+	struct usb_ep		*in_ep, *out_ep;
+	struct snd_card 	*card;
+	struct snd_rawmidi	*rmidi;
+	struct snd_rawmidi_substream *in_substream;
+	struct snd_rawmidi_substream *out_substream;
+
+	/* For the moment we only support one port in
+	   each direction, but in_port is kept as a
+	   separate struct so we can have more later. */
+	struct gmidi_in_port	in_port;
+	unsigned long		out_triggered;
+	struct tasklet_struct	tasklet;
+};
+
+static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req);
+
+
+#define xprintk(d,level,fmt,args...) \
+	dev_printk(level , &(d)->gadget->dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+	xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG	DBG
+#else
+#define VDBG(dev,fmt,args...) \
+	do { } while (0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+	xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+	xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+	xprintk(dev , KERN_INFO , fmt , ## args)
+
+
+static unsigned buflen = 256;
+static unsigned qlen = 32;
+
+module_param(buflen, uint, S_IRUGO);
+module_param(qlen, uint, S_IRUGO);
+
+
+/* Thanks to Grey Innovation for donating this product ID.
+ *
+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+#define DRIVER_VENDOR_NUM	0x17b3		/* Grey Innovation */
+#define DRIVER_PRODUCT_NUM	0x0004		/* Linux-USB "MIDI Gadget" */
+
+
+/*
+ * DESCRIPTORS ... most are static, but strings and (full)
+ * configuration descriptors are built on demand.
+ */
+
+#define STRING_MANUFACTURER	25
+#define STRING_PRODUCT		42
+#define STRING_SERIAL		101
+#define STRING_MIDI_GADGET	250
+
+/* We only have the one configuration, it's number 1. */
+#define	GMIDI_CONFIG		1
+
+/* We have two interfaces- AudioControl and MIDIStreaming */
+#define GMIDI_AC_INTERFACE	0
+#define GMIDI_MS_INTERFACE	1
+#define GMIDI_NUM_INTERFACES	2
+
+DECLARE_USB_AC_HEADER_DESCRIPTOR(1);
+DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
+DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1);
+
+/* B.1  Device Descriptor */
+static struct usb_device_descriptor device_desc = {
+	.bLength =		USB_DT_DEVICE_SIZE,
+	.bDescriptorType =	USB_DT_DEVICE,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
+	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+	.iManufacturer =	STRING_MANUFACTURER,
+	.iProduct =		STRING_PRODUCT,
+	.bNumConfigurations =	1,
+};
+
+/* B.2  Configuration Descriptor */
+static struct usb_config_descriptor config_desc = {
+	.bLength =		USB_DT_CONFIG_SIZE,
+	.bDescriptorType =	USB_DT_CONFIG,
+	/* compute wTotalLength on the fly */
+	.bNumInterfaces =	GMIDI_NUM_INTERFACES,
+	.bConfigurationValue =	GMIDI_CONFIG,
+	.iConfiguration =	STRING_MIDI_GADGET,
+	/*
+	 * FIXME: When embedding this driver in a device,
+	 * these need to be set to reflect the actual
+	 * power properties of the device. Is it selfpowered?
+	 */
+	.bmAttributes =		USB_CONFIG_ATT_ONE,
+	.bMaxPower =		1,
+};
+
+/* B.3.1  Standard AC Interface Descriptor */
+static const struct usb_interface_descriptor ac_interface_desc = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bInterfaceNumber =	GMIDI_AC_INTERFACE,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_AUDIO,
+	.bInterfaceSubClass =	USB_SUBCLASS_AUDIOCONTROL,
+	.iInterface =		STRING_MIDI_GADGET,
+};
+
+/* B.3.2  Class-Specific AC Interface Descriptor */
+static const struct usb_ac_header_descriptor_1 ac_header_desc = {
+	.bLength =		USB_DT_AC_HEADER_SIZE(1),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype =	USB_MS_HEADER,
+	.bcdADC =		__constant_cpu_to_le16(0x0100),
+	.wTotalLength =		USB_DT_AC_HEADER_SIZE(1),
+	.bInCollection =	1,
+	.baInterfaceNr = {
+		[0] =		GMIDI_MS_INTERFACE,
+	}
+};
+
+/* B.4.1  Standard MS Interface Descriptor */
+static const struct usb_interface_descriptor ms_interface_desc = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bInterfaceNumber =	GMIDI_MS_INTERFACE,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_AUDIO,
+	.bInterfaceSubClass =	USB_SUBCLASS_MIDISTREAMING,
+	.iInterface =		STRING_MIDI_GADGET,
+};
+
+/* B.4.2  Class-Specific MS Interface Descriptor */
+static const struct usb_ms_header_descriptor ms_header_desc = {
+	.bLength =		USB_DT_MS_HEADER_SIZE,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype =	USB_MS_HEADER,
+	.bcdMSC =		__constant_cpu_to_le16(0x0100),
+	.wTotalLength =		USB_DT_MS_HEADER_SIZE
+				+ 2*USB_DT_MIDI_IN_SIZE
+				+ 2*USB_DT_MIDI_OUT_SIZE(1),
+};
+
+#define JACK_IN_EMB	1
+#define JACK_IN_EXT	2
+#define JACK_OUT_EMB	3
+#define JACK_OUT_EXT	4
+
+/* B.4.3  MIDI IN Jack Descriptors */
+static const struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
+	.bLength =		USB_DT_MIDI_IN_SIZE,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype =	USB_MS_MIDI_IN_JACK,
+	.bJackType =		USB_MS_EMBEDDED,
+	.bJackID =		JACK_IN_EMB,
+};
+
+static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = {
+	.bLength =		USB_DT_MIDI_IN_SIZE,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype =	USB_MS_MIDI_IN_JACK,
+	.bJackType =		USB_MS_EXTERNAL,
+	.bJackID =		JACK_IN_EXT,
+};
+
+/* B.4.4  MIDI OUT Jack Descriptors */
+static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = {
+	.bLength =		USB_DT_MIDI_OUT_SIZE(1),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK,
+	.bJackType =		USB_MS_EMBEDDED,
+	.bJackID =		JACK_OUT_EMB,
+	.bNrInputPins =		1,
+	.pins = {
+		[0] = {
+			.baSourceID =	JACK_IN_EXT,
+			.baSourcePin =	1,
+		}
+	}
+};
+
+static const struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc = {
+	.bLength =		USB_DT_MIDI_OUT_SIZE(1),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK,
+	.bJackType =		USB_MS_EXTERNAL,
+	.bJackID =		JACK_OUT_EXT,
+	.bNrInputPins =		1,
+	.pins = {
+		[0] = {
+			.baSourceID =	JACK_IN_EMB,
+			.baSourcePin =	1,
+		}
+	}
+};
+
+/* B.5.1  Standard Bulk OUT Endpoint Descriptor */
+static struct usb_endpoint_descriptor bulk_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_AUDIO_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+/* B.5.2  Class-specific MS Bulk OUT Endpoint Descriptor */
+static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = {
+	.bLength =		USB_DT_MS_ENDPOINT_SIZE(1),
+	.bDescriptorType =	USB_DT_CS_ENDPOINT,
+	.bDescriptorSubtype =	USB_MS_GENERAL,
+	.bNumEmbMIDIJack =	1,
+	.baAssocJackID = {
+		[0] =		JACK_IN_EMB,
+	}
+};
+
+/* B.6.1  Standard Bulk IN Endpoint Descriptor */
+static struct usb_endpoint_descriptor bulk_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_AUDIO_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+/* B.6.2  Class-specific MS Bulk IN Endpoint Descriptor */
+static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = {
+	.bLength =		USB_DT_MS_ENDPOINT_SIZE(1),
+	.bDescriptorType =	USB_DT_CS_ENDPOINT,
+	.bDescriptorSubtype =	USB_MS_GENERAL,
+	.bNumEmbMIDIJack =	1,
+	.baAssocJackID = {
+		[0] =		JACK_OUT_EMB,
+	}
+};
+
+static const struct usb_descriptor_header *gmidi_function [] = {
+	(struct usb_descriptor_header *)&ac_interface_desc,
+	(struct usb_descriptor_header *)&ac_header_desc,
+	(struct usb_descriptor_header *)&ms_interface_desc,
+
+	(struct usb_descriptor_header *)&ms_header_desc,
+	(struct usb_descriptor_header *)&jack_in_emb_desc,
+	(struct usb_descriptor_header *)&jack_in_ext_desc,
+	(struct usb_descriptor_header *)&jack_out_emb_desc,
+	(struct usb_descriptor_header *)&jack_out_ext_desc,
+	/* If you add more jacks, update ms_header_desc.wTotalLength */
+
+	(struct usb_descriptor_header *)&bulk_out_desc,
+	(struct usb_descriptor_header *)&ms_out_desc,
+	(struct usb_descriptor_header *)&bulk_in_desc,
+	(struct usb_descriptor_header *)&ms_in_desc,
+	NULL,
+};
+
+static char manufacturer[50];
+static char product_desc[40] = "MIDI Gadget";
+static char serial_number[20];
+
+/* static strings, in UTF-8 */
+static struct usb_string strings [] = {
+	{ STRING_MANUFACTURER, manufacturer, },
+	{ STRING_PRODUCT, product_desc, },
+	{ STRING_SERIAL, serial_number, },
+	{ STRING_MIDI_GADGET, longname, },
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings,
+};
+
+static int config_buf(struct usb_gadget *gadget,
+		u8 *buf, u8 type, unsigned index)
+{
+	int len;
+
+	/* only one configuration */
+	if (index != 0) {
+		return -EINVAL;
+	}
+	len = usb_gadget_config_buf(&config_desc,
+			buf, USB_BUFSIZ, gmidi_function);
+	if (len < 0) {
+		return len;
+	}
+	((struct usb_config_descriptor *)buf)->bDescriptorType = type;
+	return len;
+}
+
+static struct usb_request* alloc_ep_req(struct usb_ep *ep, unsigned length)
+{
+	struct usb_request	*req;
+
+	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+	if (req) {
+		req->length = length;
+		req->buf = kmalloc(length, GFP_ATOMIC);
+		if (!req->buf) {
+			usb_ep_free_request(ep, req);
+			req = NULL;
+		}
+	}
+	return req;
+}
+
+static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+	kfree(req->buf);
+	usb_ep_free_request(ep, req);
+}
+
+static const uint8_t gmidi_cin_length[] = {
+	0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
+};
+
+/*
+ * Receives a chunk of MIDI data.
+ */
+static void gmidi_read_data(struct usb_ep *ep, int cable,
+				   uint8_t* data, int length)
+{
+	struct gmidi_device *dev = ep->driver_data;
+	/* cable is ignored, because for now we only have one. */
+
+	if (!dev->out_substream) {
+		/* Nobody is listening - throw it on the floor. */
+		return;
+	}
+	if (!test_bit(dev->out_substream->number, &dev->out_triggered)) {
+		return;
+	}
+	snd_rawmidi_receive(dev->out_substream, data, length);
+}
+
+static void gmidi_handle_out_data(struct usb_ep *ep, struct usb_request *req)
+{
+	unsigned i;
+	u8 *buf = req->buf;
+
+	for (i = 0; i + 3 < req->actual; i += 4) {
+		if (buf[i] != 0) {
+			int cable = buf[i] >> 4;
+			int length = gmidi_cin_length[buf[i] & 0x0f];
+			gmidi_read_data(ep, cable, &buf[i + 1], length);
+		}
+	}
+}
+
+static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct gmidi_device *dev = ep->driver_data;
+	int status = req->status;
+
+	switch (status) {
+	case 0: 			/* normal completion */
+		if (ep == dev->out_ep) {
+			/* we received stuff.
+			   req is queued again, below */
+			gmidi_handle_out_data(ep, req);
+		} else if (ep == dev->in_ep) {
+			/* our transmit completed.
+			   see if there's more to go.
+			   gmidi_transmit eats req, don't queue it again. */
+			gmidi_transmit(dev, req);
+			return;
+		}
+		break;
+
+	/* this endpoint is normally active while we're configured */
+	case -ECONNABORTED: 		/* hardware forced ep reset */
+	case -ECONNRESET:		/* request dequeued */
+	case -ESHUTDOWN:		/* disconnect from host */
+		VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
+				req->actual, req->length);
+		if (ep == dev->out_ep) {
+			gmidi_handle_out_data(ep, req);
+		}
+		free_ep_req(ep, req);
+		return;
+
+	case -EOVERFLOW:		/* buffer overrun on read means that
+					 * we didn't provide a big enough
+					 * buffer.
+					 */
+	default:
+		DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
+				status, req->actual, req->length);
+		break;
+	case -EREMOTEIO:		/* short read */
+		break;
+	}
+
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (status) {
+		ERROR(dev, "kill %s:  resubmit %d bytes --> %d\n",
+				ep->name, req->length, status);
+		usb_ep_set_halt(ep);
+		/* FIXME recover later ... somehow */
+	}
+}
+
+static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags)
+{
+	int err = 0;
+	struct usb_request *req;
+	struct usb_ep* ep;
+	unsigned i;
+
+	err = usb_ep_enable(dev->in_ep, &bulk_in_desc);
+	if (err) {
+		ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err);
+		goto fail;
+	}
+	dev->in_ep->driver_data = dev;
+
+	err = usb_ep_enable(dev->out_ep, &bulk_out_desc);
+	if (err) {
+		ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err);
+		goto fail;
+	}
+	dev->out_ep->driver_data = dev;
+
+	/* allocate a bunch of read buffers and queue them all at once. */
+	ep = dev->out_ep;
+	for (i = 0; i < qlen && err == 0; i++) {
+		req = alloc_ep_req(ep, buflen);
+		if (req) {
+			req->complete = gmidi_complete;
+			err = usb_ep_queue(ep, req, GFP_ATOMIC);
+			if (err) {
+				DBG(dev, "%s queue req: %d\n", ep->name, err);
+			}
+		} else {
+			err = -ENOMEM;
+		}
+	}
+fail:
+	/* caller is responsible for cleanup on error */
+	return err;
+}
+
+
+static void gmidi_reset_config(struct gmidi_device *dev)
+{
+	if (dev->config == 0) {
+		return;
+	}
+
+	DBG(dev, "reset config\n");
+
+	/* just disable endpoints, forcing completion of pending i/o.
+	 * all our completion handlers free their requests in this case.
+	 */
+	usb_ep_disable(dev->in_ep);
+	usb_ep_disable(dev->out_ep);
+	dev->config = 0;
+}
+
+/* change our operational config.  this code must agree with the code
+ * that returns config descriptors, and altsetting code.
+ *
+ * it's also responsible for power management interactions. some
+ * configurations might not work with our current power sources.
+ *
+ * note that some device controller hardware will constrain what this
+ * code can do, perhaps by disallowing more than one configuration or
+ * by limiting configuration choices (like the pxa2xx).
+ */
+static int
+gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags)
+{
+	int result = 0;
+	struct usb_gadget *gadget = dev->gadget;
+
+#if 0
+	/* FIXME */
+	/* Hacking this bit out fixes a bug where on receipt of two
+	   USB_REQ_SET_CONFIGURATION messages, we end up with no
+	   buffered OUT requests waiting for data. This is clearly
+	   hiding a bug elsewhere, because if the config didn't
+	   change then we really shouldn't do anything. */
+	/* Having said that, when we do "change" from config 1
+	   to config 1, we at least gmidi_reset_config() which
+	   clears out any requests on endpoints, so it's not like
+	   we leak or anything. */
+	if (number == dev->config) {
+		return 0;
+	}
+#endif
+
+	if (gadget_is_sa1100(gadget) && dev->config) {
+		/* tx fifo is full, but we can't clear it...*/
+		INFO(dev, "can't change configurations\n");
+		return -ESPIPE;
+	}
+	gmidi_reset_config(dev);
+
+	switch (number) {
+	case GMIDI_CONFIG:
+		result = set_gmidi_config(dev, gfp_flags);
+		break;
+	default:
+		result = -EINVAL;
+		/* FALL THROUGH */
+	case 0:
+		return result;
+	}
+
+	if (!result && (!dev->in_ep || !dev->out_ep)) {
+		result = -ENODEV;
+	}
+	if (result) {
+		gmidi_reset_config(dev);
+	} else {
+		char *speed;
+
+		switch (gadget->speed) {
+		case USB_SPEED_LOW:	speed = "low"; break;
+		case USB_SPEED_FULL:	speed = "full"; break;
+		case USB_SPEED_HIGH:	speed = "high"; break;
+		default: 		speed = "?"; break;
+		}
+
+		dev->config = number;
+		INFO(dev, "%s speed\n", speed);
+	}
+	return result;
+}
+
+
+static void gmidi_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length) {
+		DBG((struct gmidi_device *) ep->driver_data,
+				"setup complete --> %d, %d/%d\n",
+				req->status, req->actual, req->length);
+	}
+}
+
+/*
+ * The setup() callback implements all the ep0 functionality that's
+ * not handled lower down, in hardware or the hardware driver (like
+ * device and endpoint feature flags, and their status).  It's all
+ * housekeeping for the gadget function we're implementing.  Most of
+ * the work is in config-specific setup.
+ */
+static int gmidi_setup(struct usb_gadget *gadget,
+			const struct usb_ctrlrequest *ctrl)
+{
+	struct gmidi_device *dev = get_gadget_data(gadget);
+	struct usb_request *req = dev->req;
+	int value = -EOPNOTSUPP;
+	u16 w_index = le16_to_cpu(ctrl->wIndex);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 w_length = le16_to_cpu(ctrl->wLength);
+
+	/* usually this stores reply data in the pre-allocated ep0 buffer,
+	 * but config change events will reconfigure hardware.
+	 */
+	req->zero = 0;
+	switch (ctrl->bRequest) {
+
+	case USB_REQ_GET_DESCRIPTOR:
+		if (ctrl->bRequestType != USB_DIR_IN) {
+			goto unknown;
+		}
+		switch (w_value >> 8) {
+
+		case USB_DT_DEVICE:
+			value = min(w_length, (u16) sizeof(device_desc));
+			memcpy(req->buf, &device_desc, value);
+			break;
+		case USB_DT_CONFIG:
+			value = config_buf(gadget, req->buf,
+					w_value >> 8,
+					w_value & 0xff);
+			if (value >= 0) {
+				value = min(w_length, (u16)value);
+			}
+			break;
+
+		case USB_DT_STRING:
+			/* wIndex == language code.
+			 * this driver only handles one language, you can
+			 * add string tables for other languages, using
+			 * any UTF-8 characters
+			 */
+			value = usb_gadget_get_string(&stringtab,
+					w_value & 0xff, req->buf);
+			if (value >= 0) {
+				value = min(w_length, (u16)value);
+			}
+			break;
+		}
+		break;
+
+	/* currently two configs, two speeds */
+	case USB_REQ_SET_CONFIGURATION:
+		if (ctrl->bRequestType != 0) {
+			goto unknown;
+		}
+		if (gadget->a_hnp_support) {
+			DBG(dev, "HNP available\n");
+		} else if (gadget->a_alt_hnp_support) {
+			DBG(dev, "HNP needs a different root port\n");
+		} else {
+			VDBG(dev, "HNP inactive\n");
+		}
+		spin_lock(&dev->lock);
+		value = gmidi_set_config(dev, w_value, GFP_ATOMIC);
+		spin_unlock(&dev->lock);
+		break;
+	case USB_REQ_GET_CONFIGURATION:
+		if (ctrl->bRequestType != USB_DIR_IN) {
+			goto unknown;
+		}
+		*(u8 *)req->buf = dev->config;
+		value = min(w_length, (u16)1);
+		break;
+
+	/* until we add altsetting support, or other interfaces,
+	 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
+	 * and already killed pending endpoint I/O.
+	 */
+	case USB_REQ_SET_INTERFACE:
+		if (ctrl->bRequestType != USB_RECIP_INTERFACE) {
+			goto unknown;
+		}
+		spin_lock(&dev->lock);
+		if (dev->config && w_index < GMIDI_NUM_INTERFACES
+			&& w_value == 0)
+		{
+			u8 config = dev->config;
+
+			/* resets interface configuration, forgets about
+			 * previous transaction state (queued bufs, etc)
+			 * and re-inits endpoint state (toggle etc)
+			 * no response queued, just zero status == success.
+			 * if we had more than one interface we couldn't
+			 * use this "reset the config" shortcut.
+			 */
+			gmidi_reset_config(dev);
+			gmidi_set_config(dev, config, GFP_ATOMIC);
+			value = 0;
+		}
+		spin_unlock(&dev->lock);
+		break;
+	case USB_REQ_GET_INTERFACE:
+		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) {
+			goto unknown;
+		}
+		if (!dev->config) {
+			break;
+		}
+		if (w_index >= GMIDI_NUM_INTERFACES) {
+			value = -EDOM;
+			break;
+		}
+		*(u8 *)req->buf = 0;
+		value = min(w_length, (u16)1);
+		break;
+
+	default:
+unknown:
+		VDBG(dev, "unknown control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* respond with data transfer before status phase? */
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < w_length;
+		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			DBG(dev, "ep_queue --> %d\n", value);
+			req->status = 0;
+			gmidi_setup_complete(gadget->ep0, req);
+		}
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static void gmidi_disconnect(struct usb_gadget *gadget)
+{
+	struct gmidi_device *dev = get_gadget_data(gadget);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	gmidi_reset_config(dev);
+
+	/* a more significant application might have some non-usb
+	 * activities to quiesce here, saving resources like power
+	 * or pushing the notification up a network stack.
+	 */
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* next we may get setup() calls to enumerate new connections;
+	 * or an unbind() during shutdown (including removing module).
+	 */
+}
+
+static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget)
+{
+	struct gmidi_device *dev = get_gadget_data(gadget);
+	struct snd_card* card;
+
+	DBG(dev, "unbind\n");
+
+	card = dev->card;
+	dev->card = NULL;
+	if (card) {
+		snd_card_free(card);
+	}
+
+	/* we've already been disconnected ... no i/o is active */
+	if (dev->req) {
+		dev->req->length = USB_BUFSIZ;
+		free_ep_req(gadget->ep0, dev->req);
+	}
+	kfree(dev);
+	set_gadget_data(gadget, NULL);
+}
+
+static int gmidi_snd_free(struct snd_device *device)
+{
+	return 0;
+}
+
+static void gmidi_transmit_packet(struct usb_request* req, uint8_t p0,
+					uint8_t p1, uint8_t p2, uint8_t p3)
+{
+	unsigned length = req->length;
+
+	uint8_t* buf = (uint8_t*)req->buf + length;
+	buf[0] = p0;
+	buf[1] = p1;
+	buf[2] = p2;
+	buf[3] = p3;
+	req->length = length + 4;
+}
+
+/*
+ * Converts MIDI commands to USB MIDI packets.
+ */
+static void gmidi_transmit_byte(struct usb_request* req,
+				struct gmidi_in_port* port, uint8_t b)
+{
+	uint8_t p0 = port->cable;
+
+	if (b >= 0xf8) {
+		gmidi_transmit_packet(req, p0 | 0x0f, b, 0, 0);
+	} else if (b >= 0xf0) {
+		switch (b) {
+		case 0xf0:
+			port->data[0] = b;
+			port->state = STATE_SYSEX_1;
+			break;
+		case 0xf1:
+		case 0xf3:
+			port->data[0] = b;
+			port->state = STATE_1PARAM;
+			break;
+		case 0xf2:
+			port->data[0] = b;
+			port->state = STATE_2PARAM_1;
+			break;
+		case 0xf4:
+		case 0xf5:
+			port->state = STATE_UNKNOWN;
+			break;
+		case 0xf6:
+			gmidi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0);
+			port->state = STATE_UNKNOWN;
+			break;
+		case 0xf7:
+			switch (port->state) {
+			case STATE_SYSEX_0:
+				gmidi_transmit_packet(req,
+					p0 | 0x05, 0xf7, 0, 0);
+				break;
+			case STATE_SYSEX_1:
+				gmidi_transmit_packet(req,
+					p0 | 0x06, port->data[0], 0xf7, 0);
+				break;
+			case STATE_SYSEX_2:
+				gmidi_transmit_packet(req,
+					p0 | 0x07, port->data[0],
+					port->data[1], 0xf7);
+				break;
+			}
+			port->state = STATE_UNKNOWN;
+			break;
+		}
+	} else if (b >= 0x80) {
+		port->data[0] = b;
+		if (b >= 0xc0 && b <= 0xdf)
+			port->state = STATE_1PARAM;
+		else
+			port->state = STATE_2PARAM_1;
+	} else { /* b < 0x80 */
+		switch (port->state) {
+		case STATE_1PARAM:
+			if (port->data[0] < 0xf0) {
+				p0 |= port->data[0] >> 4;
+			} else {
+				p0 |= 0x02;
+				port->state = STATE_UNKNOWN;
+			}
+			gmidi_transmit_packet(req, p0, port->data[0], b, 0);
+			break;
+		case STATE_2PARAM_1:
+			port->data[1] = b;
+			port->state = STATE_2PARAM_2;
+			break;
+		case STATE_2PARAM_2:
+			if (port->data[0] < 0xf0) {
+				p0 |= port->data[0] >> 4;
+				port->state = STATE_2PARAM_1;
+			} else {
+				p0 |= 0x03;
+				port->state = STATE_UNKNOWN;
+			}
+			gmidi_transmit_packet(req,
+				p0, port->data[0], port->data[1], b);
+			break;
+		case STATE_SYSEX_0:
+			port->data[0] = b;
+			port->state = STATE_SYSEX_1;
+			break;
+		case STATE_SYSEX_1:
+			port->data[1] = b;
+			port->state = STATE_SYSEX_2;
+			break;
+		case STATE_SYSEX_2:
+			gmidi_transmit_packet(req,
+				p0 | 0x04, port->data[0], port->data[1], b);
+			port->state = STATE_SYSEX_0;
+			break;
+		}
+	}
+}
+
+static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req)
+{
+	struct usb_ep* ep = dev->in_ep;
+	struct gmidi_in_port* port = &dev->in_port;
+
+	if (!ep) {
+		return;
+	}
+	if (!req) {
+		req = alloc_ep_req(ep, buflen);
+	}
+	if (!req) {
+		ERROR(dev, "gmidi_transmit: alloc_ep_request failed\n");
+		return;
+	}
+	req->length = 0;
+	req->complete = gmidi_complete;
+
+	if (port->active) {
+		while (req->length + 3 < buflen) {
+			uint8_t b;
+			if (snd_rawmidi_transmit(dev->in_substream, &b, 1)
+				!= 1)
+			{
+				port->active = 0;
+				break;
+			}
+			gmidi_transmit_byte(req, port, b);
+		}
+	}
+	if (req->length > 0) {
+		usb_ep_queue(ep, req, GFP_ATOMIC);
+	} else {
+		free_ep_req(ep, req);
+	}
+}
+
+static void gmidi_in_tasklet(unsigned long data)
+{
+	struct gmidi_device* dev = (struct gmidi_device*)data;
+
+	gmidi_transmit(dev, NULL);
+}
+
+static int gmidi_in_open(struct snd_rawmidi_substream *substream)
+{
+	struct gmidi_device* dev = substream->rmidi->private_data;
+
+	VDBG(dev, "gmidi_in_open\n");
+	dev->in_substream = substream;
+	dev->in_port.state = STATE_UNKNOWN;
+	return 0;
+}
+
+static int gmidi_in_close(struct snd_rawmidi_substream *substream)
+{
+	VDBG(dev, "gmidi_in_close\n");
+	return 0;
+}
+
+static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+	struct gmidi_device* dev = substream->rmidi->private_data;
+
+	VDBG(dev, "gmidi_in_trigger %d\n", up);
+	dev->in_port.active = up;
+	if (up) {
+		tasklet_hi_schedule(&dev->tasklet);
+	}
+}
+
+static int gmidi_out_open(struct snd_rawmidi_substream *substream)
+{
+	struct gmidi_device* dev = substream->rmidi->private_data;
+
+	VDBG(dev, "gmidi_out_open\n");
+	dev->out_substream = substream;
+	return 0;
+}
+
+static int gmidi_out_close(struct snd_rawmidi_substream *substream)
+{
+	VDBG(dev, "gmidi_out_close\n");
+	return 0;
+}
+
+static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+	struct gmidi_device* dev = substream->rmidi->private_data;
+
+	VDBG(dev, "gmidi_out_trigger %d\n", up);
+	if (up) {
+		set_bit(substream->number, &dev->out_triggered);
+	} else {
+		clear_bit(substream->number, &dev->out_triggered);
+	}
+}
+
+static struct snd_rawmidi_ops gmidi_in_ops = {
+	.open = gmidi_in_open,
+	.close = gmidi_in_close,
+	.trigger = gmidi_in_trigger,
+};
+
+static struct snd_rawmidi_ops gmidi_out_ops = {
+	.open = gmidi_out_open,
+	.close = gmidi_out_close,
+	.trigger = gmidi_out_trigger
+};
+
+/* register as a sound "card" */
+static int gmidi_register_card(struct gmidi_device *dev)
+{
+	struct snd_card *card;
+	struct snd_rawmidi *rmidi;
+	int err;
+	int out_ports = 1;
+	int in_ports = 1;
+	static struct snd_device_ops ops = {
+		.dev_free = gmidi_snd_free,
+	};
+
+	card = snd_card_new(index, id, THIS_MODULE, 0);
+	if (!card) {
+		ERROR(dev, "snd_card_new failed\n");
+		err = -ENOMEM;
+		goto fail;
+	}
+	dev->card = card;
+
+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, dev, &ops);
+	if (err < 0) {
+		ERROR(dev, "snd_device_new failed: error %d\n", err);
+		goto fail;
+	}
+
+	strcpy(card->driver, longname);
+	strcpy(card->longname, longname);
+	strcpy(card->shortname, shortname);
+
+	/* Set up rawmidi */
+	dev->in_port.dev = dev;
+	dev->in_port.active = 0;
+	snd_component_add(card, "MIDI");
+	err = snd_rawmidi_new(card, "USB MIDI Gadget", 0,
+			      out_ports, in_ports, &rmidi);
+	if (err < 0) {
+		ERROR(dev, "snd_rawmidi_new failed: error %d\n", err);
+		goto fail;
+	}
+	dev->rmidi = rmidi;
+	strcpy(rmidi->name, card->shortname);
+	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+			    SNDRV_RAWMIDI_INFO_INPUT |
+			    SNDRV_RAWMIDI_INFO_DUPLEX;
+	rmidi->private_data = dev;
+
+	/* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.
+	   It's an upside-down world being a gadget. */
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops);
+	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops);
+
+	snd_card_set_dev(card, &dev->gadget->dev);
+
+	/* register it - we're ready to go */
+	err = snd_card_register(card);
+	if (err < 0) {
+		ERROR(dev, "snd_card_register failed\n");
+		goto fail;
+	}
+
+	VDBG(dev, "gmidi_register_card finished ok\n");
+	return 0;
+
+fail:
+	if (dev->card) {
+		snd_card_free(dev->card);
+		dev->card = NULL;
+	}
+	return err;
+}
+
+/*
+ * Creates an output endpoint, and initializes output ports.
+ */
+static int __devinit gmidi_bind(struct usb_gadget *gadget)
+{
+	struct gmidi_device *dev;
+	struct usb_ep *in_ep, *out_ep;
+	int gcnum, err = 0;
+
+	/* support optional vendor/distro customization */
+	if (idVendor) {
+		if (!idProduct) {
+			printk(KERN_ERR "idVendor needs idProduct!\n");
+			return -ENODEV;
+		}
+		device_desc.idVendor = cpu_to_le16(idVendor);
+		device_desc.idProduct = cpu_to_le16(idProduct);
+		if (bcdDevice) {
+			device_desc.bcdDevice = cpu_to_le16(bcdDevice);
+		}
+	}
+	if (iManufacturer) {
+		strlcpy(manufacturer, iManufacturer, sizeof(manufacturer));
+	} else {
+		snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+			system_utsname.sysname, system_utsname.release,
+			gadget->name);
+	}
+	if (iProduct) {
+		strlcpy(product_desc, iProduct, sizeof(product_desc));
+	}
+	if (iSerialNumber) {
+		device_desc.iSerialNumber = STRING_SERIAL,
+		strlcpy(serial_number, iSerialNumber, sizeof(serial_number));
+	}
+
+	/* Bulk-only drivers like this one SHOULD be able to
+	 * autoconfigure on any sane usb controller driver,
+	 * but there may also be important quirks to address.
+	 */
+	usb_ep_autoconfig_reset(gadget);
+	in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc);
+	if (!in_ep) {
+autoconf_fail:
+		printk(KERN_ERR "%s: can't autoconfigure on %s\n",
+			shortname, gadget->name);
+		return -ENODEV;
+	}
+	EP_IN_NAME = in_ep->name;
+	in_ep->driver_data = in_ep;	/* claim */
+
+	out_ep = usb_ep_autoconfig(gadget, &bulk_out_desc);
+	if (!out_ep) {
+		goto autoconf_fail;
+	}
+	EP_OUT_NAME = out_ep->name;
+	out_ep->driver_data = out_ep;	/* claim */
+
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0) {
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	} else {
+		/* gmidi is so simple (no altsettings) that
+		 * it SHOULD NOT have problems with bulk-capable hardware.
+		 * so warn about unrecognized controllers, don't panic.
+		 */
+		printk(KERN_WARNING "%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+	}
+
+
+	/* ok, we made sense of the hardware ... */
+	dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+	if (!dev) {
+		return -ENOMEM;
+	}
+	spin_lock_init(&dev->lock);
+	dev->gadget = gadget;
+	dev->in_ep = in_ep;
+	dev->out_ep = out_ep;
+	set_gadget_data(gadget, dev);
+	tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);
+
+	/* preallocate control response and buffer */
+	dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+	if (!dev->req) {
+		err = -ENOMEM;
+		goto fail;
+	}
+	dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ,
+				&dev->req->dma, GFP_KERNEL);
+	if (!dev->req->buf) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	dev->req->complete = gmidi_setup_complete;
+
+	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+
+	gadget->ep0->driver_data = dev;
+
+	INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
+	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
+		EP_OUT_NAME, EP_IN_NAME);
+
+	/* register as an ALSA sound card */
+	err = gmidi_register_card(dev);
+	if (err < 0) {
+		goto fail;
+	}
+
+	VDBG(dev, "gmidi_bind finished ok\n");
+	return 0;
+
+fail:
+	gmidi_unbind(gadget);
+	return err;
+}
+
+
+static void gmidi_suspend(struct usb_gadget *gadget)
+{
+	struct gmidi_device *dev = get_gadget_data(gadget);
+
+	if (gadget->speed == USB_SPEED_UNKNOWN) {
+		return;
+	}
+
+	DBG(dev, "suspend\n");
+}
+
+static void gmidi_resume(struct usb_gadget *gadget)
+{
+	struct gmidi_device *dev = get_gadget_data(gadget);
+
+	DBG(dev, "resume\n");
+}
+
+
+static struct usb_gadget_driver gmidi_driver = {
+	.speed		= USB_SPEED_FULL,
+	.function	= (char *)longname,
+	.bind		= gmidi_bind,
+	.unbind		= __exit_p(gmidi_unbind),
+
+	.setup		= gmidi_setup,
+	.disconnect	= gmidi_disconnect,
+
+	.suspend	= gmidi_suspend,
+	.resume		= gmidi_resume,
+
+	.driver 	= {
+		.name		= (char *)shortname,
+		.owner		= THIS_MODULE,
+	},
+};
+
+static int __init gmidi_init(void)
+{
+	return usb_gadget_register_driver(&gmidi_driver);
+}
+module_init(gmidi_init);
+
+static void __exit gmidi_cleanup(void)
+{
+	usb_gadget_unregister_driver(&gmidi_driver);
+}
+module_exit(gmidi_cleanup);
+
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 2a7162d..4655522 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -32,6 +32,7 @@
 #include <linux/compiler.h>
 #include <asm/uaccess.h>
 #include <linux/slab.h>
+#include <linux/poll.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -222,7 +223,6 @@
 	/* needs no more cleanup */
 	BUG_ON (!list_empty (&data->epfiles));
 	BUG_ON (waitqueue_active (&data->wait));
-	BUG_ON (down_trylock (&data->lock) != 0);
 	kfree (data);
 }
 
@@ -477,6 +477,10 @@
 ep_release (struct inode *inode, struct file *fd)
 {
 	struct ep_data		*data = fd->private_data;
+	int value;
+
+	if ((value = down_interruptible(&data->lock)) < 0)
+		return value;
 
 	/* clean up if this can be reopened */
 	if (data->state != STATE_EP_UNBOUND) {
@@ -485,6 +489,7 @@
 		data->hs_desc.bDescriptorType = 0;
 		usb_ep_disable(data->ep);
 	}
+	up (&data->lock);
 	put_ep (data);
 	return 0;
 }
@@ -709,7 +714,7 @@
 /*----------------------------------------------------------------------*/
 
 /* used after endpoint configuration */
-static struct file_operations ep_io_operations = {
+static const struct file_operations ep_io_operations = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
@@ -741,7 +746,7 @@
 	struct ep_data		*data = fd->private_data;
 	struct usb_ep		*ep;
 	u32			tag;
-	int			value;
+	int			value, length = len;
 
 	if ((value = down_interruptible (&data->lock)) < 0)
 		return value;
@@ -792,7 +797,6 @@
 			goto fail0;
 		}
 	}
-	value = len;
 
 	spin_lock_irq (&data->dev->lock);
 	if (data->dev->state == STATE_DEV_UNBOUND) {
@@ -822,8 +826,10 @@
 				data->name);
 		data->state = STATE_EP_DEFER_ENABLE;
 	}
-	if (value == 0)
+	if (value == 0) {
 		fd->f_op = &ep_io_operations;
+		value = length;
+	}
 gone:
 	spin_unlock_irq (&data->dev->lock);
 	if (value < 0) {
@@ -867,7 +873,7 @@
 }
 
 /* used before endpoint configuration */
-static struct file_operations ep_config_operations = {
+static const struct file_operations ep_config_operations = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
@@ -1009,7 +1015,7 @@
 			else {
 				len = min (len, (size_t)dev->req->actual);
 // FIXME don't call this with the spinlock held ...
-				if (copy_to_user (buf, &dev->req->buf, len))
+				if (copy_to_user (buf, dev->req->buf, len))
 					retval = -EFAULT;
 				clean_req (dev->gadget->ep0, dev->req);
 				/* NOTE userspace can't yet choose to stall */
@@ -1229,6 +1235,35 @@
 	return 0;
 }
 
+static unsigned int
+ep0_poll (struct file *fd, poll_table *wait)
+{
+       struct dev_data         *dev = fd->private_data;
+       int                     mask = 0;
+
+       poll_wait(fd, &dev->wait, wait);
+
+       spin_lock_irq (&dev->lock);
+
+       /* report fd mode change before acting on it */
+       if (dev->setup_abort) {
+               dev->setup_abort = 0;
+               mask = POLLHUP;
+               goto out;
+       }
+
+       if (dev->state == STATE_SETUP) {
+               if (dev->setup_in || dev->setup_can_stall)
+                       mask = POLLOUT;
+       } else {
+               if (dev->ev_next != 0)
+                       mask = POLLIN;
+       }
+out:
+       spin_unlock_irq(&dev->lock);
+       return mask;
+}
+
 static int dev_ioctl (struct inode *inode, struct file *fd,
 		unsigned code, unsigned long value)
 {
@@ -1241,14 +1276,14 @@
 }
 
 /* used after device configuration */
-static struct file_operations ep0_io_operations = {
+static const struct file_operations ep0_io_operations = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
 	.read =		ep0_read,
 	.write =	ep0_write,
 	.fasync =	ep0_fasync,
-	// .poll =	ep0_poll,
+	.poll =		ep0_poll,
 	.ioctl =	dev_ioctl,
 	.release =	dev_release,
 };
@@ -1696,16 +1731,17 @@
 {
 	struct dev_data		*dev = get_gadget_data (gadget);
 
+	spin_lock (&dev->lock);
 	if (dev->state == STATE_UNCONNECTED) {
 		DBG (dev, "already unconnected\n");
-		return;
+		goto exit;
 	}
 	dev->state = STATE_UNCONNECTED;
 
 	INFO (dev, "disconnected\n");
-	spin_lock (&dev->lock);
 	next_event (dev, GADGETFS_DISCONNECT);
 	ep0_readable (dev);
+exit:
 	spin_unlock (&dev->lock);
 }
 
@@ -1922,7 +1958,7 @@
 	return value;
 }
 
-static struct file_operations dev_init_operations = {
+static const struct file_operations dev_init_operations = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 0924323..3bda37f 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2,7 +2,7 @@
  * Driver for the PLX NET2280 USB device controller.
  * Specs and errata are available from <http://www.plxtech.com>.
  *
- * PLX Technology Inc. (formerly NetChip Technology) supported the 
+ * PLX Technology Inc. (formerly NetChip Technology) supported the
  * development of this driver.
  *
  *
@@ -26,7 +26,8 @@
  * Copyright (C) 2003 David Brownell
  * Copyright (C) 2003-2005 PLX Technology, Inc.
  *
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
+ *	with 2282 chip
  *
  * 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
@@ -85,7 +86,7 @@
 static const char driver_desc [] = DRIVER_DESC;
 
 static const char ep0name [] = "ep0";
-static const char *ep_name [] = {
+static const char *const ep_name [] = {
 	ep0name,
 	"ep-a", "ep-b", "ep-c", "ep-d",
 	"ep-e", "ep-f",
@@ -225,7 +226,9 @@
 	if (!ep->is_in)
 		writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
 	else if (dev->pdev->device != 0x2280) {
-		/* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
+		/* Added for 2282, Don't use nak packets on an in endpoint,
+		 * this was ignored on 2280
+		 */
 		writel ((1 << CLEAR_NAK_OUT_PACKETS)
 			| (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
 	}
@@ -288,7 +291,7 @@
 	return -ETIMEDOUT;
 }
 
-static struct usb_ep_ops net2280_ep_ops;
+static const struct usb_ep_ops net2280_ep_ops;
 
 static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
 {
@@ -449,34 +452,15 @@
 
 /*-------------------------------------------------------------------------*/
 
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls.  (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
+/*
+ * dma-coherent memory allocation (for dma-capable endpoints)
  *
- * other platforms need more care, with 2.5 having a moderately general
- * solution (which falls down for allocations smaller than one page)
- * that improves significantly on the 2.4 PCI allocators by removing
- * the restriction that memory never be freed in_interrupt().
+ * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
+ * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
+ * respect to calls with irqs disabled:  alloc is safe, free is not.
+ * We currently work around (b), but not (a).
  */
-#if	defined(CONFIG_X86)
-#define USE_KMALLOC
 
-#elif	defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
-
-#elif	defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
-#define USE_KMALLOC
-
-/* FIXME there are other cases, including an x86-64 one ...  */
-#endif
-
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy.  with
- * some kinds of system caches, further tweaks may still be needed.
- */
 static void *
 net2280_alloc_buffer (
 	struct usb_ep		*_ep,
@@ -493,43 +477,71 @@
 		return NULL;
 	*dma = DMA_ADDR_INVALID;
 
-#if	defined(USE_KMALLOC)
-	retval = kmalloc(bytes, gfp_flags);
-	if (retval)
-		*dma = virt_to_phys(retval);
-#else
-	if (ep->dma) {
-		/* the main problem with this call is that it wastes memory
-		 * on typical 1/N page allocations: it allocates 1-N pages.
-		 */
-#warning Using dma_alloc_coherent even with buffers smaller than a page.
+	if (ep->dma)
 		retval = dma_alloc_coherent(&ep->dev->pdev->dev,
 				bytes, dma, gfp_flags);
-	} else
+	else
 		retval = kmalloc(bytes, gfp_flags);
-#endif
 	return retval;
 }
 
+static DEFINE_SPINLOCK(buflock);
+static LIST_HEAD(buffers);
+
+struct free_record {
+	struct list_head	list;
+	struct device		*dev;
+	unsigned		bytes;
+	dma_addr_t		dma;
+};
+
+static void do_free(unsigned long ignored)
+{
+	spin_lock_irq(&buflock);
+	while (!list_empty(&buffers)) {
+		struct free_record	*buf;
+
+		buf = list_entry(buffers.next, struct free_record, list);
+		list_del(&buf->list);
+		spin_unlock_irq(&buflock);
+
+		dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
+
+		spin_lock_irq(&buflock);
+	}
+	spin_unlock_irq(&buflock);
+}
+
+static DECLARE_TASKLET(deferred_free, do_free, 0);
+
 static void
 net2280_free_buffer (
 	struct usb_ep *_ep,
-	void *buf,
+	void *address,
 	dma_addr_t dma,
 	unsigned bytes
 ) {
 	/* free memory into the right allocator */
-#ifndef	USE_KMALLOC
 	if (dma != DMA_ADDR_INVALID) {
 		struct net2280_ep	*ep;
+		struct free_record	*buf = address;
+		unsigned long		flags;
 
 		ep = container_of(_ep, struct net2280_ep, ep);
 		if (!_ep)
 			return;
-		dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
+
+		ep = container_of (_ep, struct net2280_ep, ep);
+		buf->dev = &ep->dev->pdev->dev;
+		buf->bytes = bytes;
+		buf->dma = dma;
+
+		spin_lock_irqsave(&buflock, flags);
+		list_add_tail(&buf->list, &buffers);
+		tasklet_schedule(&deferred_free);
+		spin_unlock_irqrestore(&buflock, flags);
 	} else
-#endif
-		kfree (buf);
+		kfree (address);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -737,7 +749,8 @@
 	 */
 	if (ep->is_in)
 		dmacount |= (1 << DMA_DIRECTION);
-	if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
+	if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0)
+			|| ep->dev->pdev->device != 0x2280)
 		dmacount |= (1 << END_OF_CHAIN);
 
 	req->valid = valid;
@@ -812,7 +825,7 @@
 
 	/* previous OUT packet might have been short */
 	if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
-		 		& (1 << NAK_OUT_PACKETS)) != 0) {
+				& (1 << NAK_OUT_PACKETS)) != 0) {
 		writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT),
 			&ep->regs->ep_stat);
 
@@ -1373,7 +1386,7 @@
 	(void) readl (&ep->regs->ep_rsp);
 }
 
-static struct usb_ep_ops net2280_ep_ops = {
+static const struct usb_ep_ops net2280_ep_ops = {
 	.enable		= net2280_enable,
 	.disable	= net2280_disable,
 
@@ -1631,7 +1644,7 @@
 	}
 
 	/* Indexed Registers */
-		// none yet 
+		// none yet
 
 	/* Statistics */
 	t = scnprintf (next, size, "\nirqs:  ");
@@ -1691,11 +1704,11 @@
 				({ char *val;
 				 switch (d->bmAttributes & 0x03) {
 				 case USB_ENDPOINT_XFER_BULK:
-				 	val = "bulk"; break;
+					val = "bulk"; break;
 				 case USB_ENDPOINT_XFER_INT:
-				 	val = "intr"; break;
+					val = "intr"; break;
 				 default:
-				 	val = "iso"; break;
+					val = "iso"; break;
 				 }; val; }),
 				le16_to_cpu (d->wMaxPacketSize) & 0x1fff,
 				ep->dma ? "dma" : "pio", ep->fifo_size
@@ -1808,8 +1821,8 @@
  * net2280_set_fifo_mode - change allocation of fifo buffers
  * @gadget: access to the net2280 device that will be updated
  * @mode: 0 for default, four 1kB buffers (ep-a through ep-d);
- * 	1 for two 2kB buffers (ep-a and ep-b only);
- * 	2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
+ *	1 for two 2kB buffers (ep-a and ep-b only);
+ *	2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
  *
  * returns zero on success, else negative errno.  when this succeeds,
  * the contents of gadget->ep_list may have changed.
@@ -2241,7 +2254,8 @@
 				req->td->dmacount = 0;
 				t = readl (&ep->regs->ep_avail);
 				dma_done (ep, req, count,
-					(ep->out_overflow || t) ? -EOVERFLOW : 0);
+					(ep->out_overflow || t)
+						? -EOVERFLOW : 0);
 			}
 
 			/* also flush to prevent erratum 0106 trouble */
@@ -2411,7 +2425,7 @@
 			, &ep->regs->ep_stat);
 		u.raw [0] = readl (&dev->usb->setup0123);
 		u.raw [1] = readl (&dev->usb->setup4567);
-		
+
 		cpu_to_le32s (&u.raw [0]);
 		cpu_to_le32s (&u.raw [1]);
 
@@ -2578,14 +2592,16 @@
 
 	/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
 	 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
-	 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT 
+	 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
 	 * only indicates a change in the reset state).
 	 */
 	if (stat & tmp) {
 		writel (tmp, &dev->regs->irqstat1);
-		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && 
-				((readl (&dev->usb->usbstat) & mask) == 0))
-				|| ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) 
+		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT))
+					&& ((readl (&dev->usb->usbstat) & mask)
+							== 0))
+				|| ((readl (&dev->usb->usbctl)
+					& (1 << VBUS_PIN)) == 0)
 			    ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
 			DEBUG (dev, "disconnect %s\n",
 					dev->driver->driver.name);
@@ -2852,7 +2868,7 @@
 
 	/* now all the pci goodies ... */
 	if (pci_enable_device (pdev) < 0) {
-   	        retval = -ENODEV;
+	        retval = -ENODEV;
 		goto done;
 	}
 	dev->enabled = 1;
@@ -2870,6 +2886,10 @@
 	}
 	dev->region = 1;
 
+	/* FIXME provide firmware download interface to put
+	 * 8051 code into the chip, e.g. to turn on PCI PM.
+	 */
+
 	base = ioremap_nocache (resource, len);
 	if (base == NULL) {
 		DEBUG (dev, "can't map memory\n");
@@ -2984,16 +3004,16 @@
 
 /*-------------------------------------------------------------------------*/
 
-static struct pci_device_id pci_ids [] = { {
-	.class = 	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask = 	~0,
+static const struct pci_device_id pci_ids [] = { {
+	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =	~0,
 	.vendor =	0x17cc,
 	.device =	0x2280,
 	.subvendor =	PCI_ANY_ID,
 	.subdevice =	PCI_ANY_ID,
 }, {
-	.class = 	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask = 	~0,
+	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =	~0,
 	.vendor =	0x17cc,
 	.device =	0x2282,
 	.subvendor =	PCI_ANY_ID,
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 2de9748..0a64504 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -40,7 +40,7 @@
 #include <linux/platform_device.h>
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/dma-mapping.h>
 
 #include <asm/byteorder.h>
@@ -2437,7 +2437,7 @@
 	return single_open(file, proc_udc_show, NULL);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
 	.open		= proc_udc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index fff027d..f1adcf8 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -150,6 +150,39 @@
 static void pxa2xx_ep_fifo_flush (struct usb_ep *ep);
 static void nuke (struct pxa2xx_ep *, int status);
 
+/* one GPIO should be used to detect VBUS from the host */
+static int is_vbus_present(void)
+{
+	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+
+	if (mach->gpio_vbus)
+		return pxa_gpio_get(mach->gpio_vbus);
+	if (mach->udc_is_connected)
+		return mach->udc_is_connected();
+	return 1;
+}
+
+/* one GPIO should control a D+ pullup, so host sees this device (or not) */
+static void pullup_off(void)
+{
+	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+
+	if (mach->gpio_pullup)
+		pxa_gpio_set(mach->gpio_pullup, 0);
+	else if (mach->udc_command)
+		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+static void pullup_on(void)
+{
+	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+
+	if (mach->gpio_pullup)
+		pxa_gpio_set(mach->gpio_pullup, 1);
+	else if (mach->udc_command)
+		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
 static void pio_irq_enable(int bEndpointAddress)
 {
         bEndpointAddress &= 0xf;
@@ -1721,6 +1754,16 @@
 
 #endif
 
+static irqreturn_t
+udc_vbus_irq(int irq, void *_dev, struct pt_regs *r)
+{
+	struct pxa2xx_udc	*dev = _dev;
+	int			vbus = pxa_gpio_get(dev->mach->gpio_vbus);
+
+	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
+	return IRQ_HANDLED;
+}
+
 
 /*-------------------------------------------------------------------------*/
 
@@ -2438,7 +2481,7 @@
 static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 {
 	struct pxa2xx_udc *dev = &memory;
-	int retval, out_dma = 1;
+	int retval, out_dma = 1, vbus_irq;
 	u32 chiprev;
 
 	/* insist on Intel/ARM/XScale */
@@ -2502,6 +2545,16 @@
 	/* other non-static parts of init */
 	dev->dev = &pdev->dev;
 	dev->mach = pdev->dev.platform_data;
+	if (dev->mach->gpio_vbus) {
+		vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR);
+		pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR)
+				| GPIO_IN);
+		set_irq_type(vbus_irq, IRQT_BOTHEDGE);
+	} else
+		vbus_irq = 0;
+	if (dev->mach->gpio_pullup)
+		pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR)
+				| GPIO_OUT | GPIO_DFLT_LOW);
 
 	init_timer(&dev->timer);
 	dev->timer.function = udc_watchdog;
@@ -2557,8 +2610,19 @@
 		HEX_DISPLAY(dev->stats.irqs);
 		LUB_DISC_BLNK_LED &= 0xff;
 #endif
-	}
+	} else
 #endif
+	if (vbus_irq) {
+		retval = request_irq(vbus_irq, udc_vbus_irq,
+				SA_INTERRUPT | SA_SAMPLE_RANDOM,
+				driver_name, dev);
+		if (retval != 0) {
+			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+				driver_name, vbus_irq, retval);
+			free_irq(IRQ_USB, dev);
+			return -EBUSY;
+		}
+	}
 	create_proc_files();
 
 	return 0;
@@ -2587,6 +2651,8 @@
 		free_irq(LUBBOCK_USB_IRQ, dev);
 	}
 #endif
+	if (dev->mach->gpio_vbus)
+		free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev);
 	platform_set_drvdata(pdev, NULL);
 	the_controller = NULL;
 	return 0;
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 19a883f..8e598c8 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -177,27 +177,19 @@
 
 static struct pxa2xx_udc *the_controller;
 
-/* one GPIO should be used to detect VBUS from the host */
-static inline int is_vbus_present(void)
+static inline int pxa_gpio_get(unsigned gpio)
 {
-	if (!the_controller->mach->udc_is_connected)
-		return 1;
-	return the_controller->mach->udc_is_connected();
+	return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
 }
 
-/* one GPIO should control a D+ pullup, so host sees this device (or not) */
-static inline void pullup_off(void)
+static inline void pxa_gpio_set(unsigned gpio, int is_on)
 {
-	if (!the_controller->mach->udc_command)
-		return;
-	the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
-}
+	int mask = GPIO_bit(gpio);
 
-static inline void pullup_on(void)
-{
-	if (!the_controller->mach->udc_command)
-		return;
-	the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+	if (is_on)
+		GPSR(gpio) = mask;
+	else
+		GPCR(gpio) = mask;
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index e762aa1..b893e31 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1120,12 +1120,15 @@
 gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2));
 			list_del(&req_entry->re_entry);
 			req->length = len;
+			spin_unlock_irqrestore(&dev->dev_lock, flags);
 			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
 				printk(KERN_ERR
 				"gs_send: cannot queue read request, ret=%d\n",
 					ret);
+				spin_lock_irqsave(&dev->dev_lock, flags);
 				break;
 			}
+			spin_lock_irqsave(&dev->dev_lock, flags);
 		} else {
 			break;
 		}
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index b93d71d..cf10cbc 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -83,6 +83,7 @@
 	tristate "OHCI HCD support"
 	depends on USB && USB_ARCH_HAS_OHCI
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
+	select I2C if ARCH_PNX4008
 	---help---
 	  The Open Host Controller Interface (OHCI) is a standard for accessing
 	  USB 1.1 host controller hardware.  It does more in hardware than Intel's
@@ -141,6 +142,34 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called uhci-hcd.
 
+config USB_U132_HCD
+	tristate "Elan U132 Adapter Host Controller"
+	depends on USB && USB_FTDI_ELAN
+	default M
+	help
+	  The U132 adapter is a USB to CardBus adapter specifically designed
+	  for PC cards that contain an OHCI host controller. Typical PC cards
+	  are the Orange Mobile 3G Option GlobeTrotter Fusion card. The U132
+	  adapter will *NOT* work with PC cards that do not contain an OHCI
+	  controller.
+
+	  For those PC cards that contain multiple OHCI controllers only ther
+	  first one is used.
+
+	  The driver consists of two modules, the "ftdi-elan" module is a
+	  USB client driver that interfaces to the FTDI chip within ELAN's
+	  USB-to-PCMCIA adapter, and this "u132-hcd" module is a USB host
+	  controller driver that talks to the OHCI controller within the
+	  CardBus cards that are inserted in the U132 adapter.
+
+	  This driver has been tested with a CardBus OHCI USB adapter, and
+	  worked with a USB PEN Drive inserted into the first USB port of
+	  the PCCARD. A rather pointless thing to do, but useful for testing.
+
+	  It is safe to say M here.
+
+	  See also <http://www.elandigitalsystems.com/support/ufaq/u132linux.php>
+
 config USB_SL811_HCD
 	tristate "SL811HS HCD support"
 	depends on USB
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index e3020f4b..a2e58c8 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -14,4 +14,5 @@
 obj-$(CONFIG_USB_UHCI_HCD)	+= uhci-hcd.o
 obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)	+= sl811_cs.o
+obj-$(CONFIG_USB_U132_HCD)	+= u132-hcd.o
 obj-$(CONFIG_ETRAX_ARCH_V10)	+= hc_crisv10.o
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 26ed757..5d1b12a 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -200,6 +200,7 @@
 	.reset = ehci_init,
 	.start = ehci_run,
 	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -268,6 +269,7 @@
 static struct platform_driver ehci_hcd_au1xxx_driver = {
 	.probe = ehci_hcd_au1xxx_drv_probe,
 	.remove = ehci_hcd_au1xxx_drv_remove,
+	.shutdown = usb_hcd_platform_shutdown,
 	/*.suspend      = ehci_hcd_au1xxx_drv_suspend, */
 	/*.resume       = ehci_hcd_au1xxx_drv_resume, */
 	.driver = {
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 65ac9fe..23b95b2 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001-2002 by David Brownell
- * 
+ *
  * 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
@@ -65,7 +65,7 @@
 		for (i = 0; i < HCS_N_PORTS (params); i++) {
 			// FIXME MIPS won't readb() ...
 			byte = readb (&ehci->caps->portroute[(i>>1)]);
-			sprintf(tmp, "%d ", 
+			sprintf(tmp, "%d ",
 				((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf)));
 			strcat(buf, tmp);
 		}
@@ -141,12 +141,12 @@
 }
 
 static void __attribute__((__unused__))
-dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) 
+dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 {
 	ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
 		label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
 	ehci_dbg (ehci,
-		"  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", 
+		"  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
 		le32_to_cpu(itd->hw_transaction[0]),
 		le32_to_cpu(itd->hw_transaction[1]),
 		le32_to_cpu(itd->hw_transaction[2]),
@@ -156,7 +156,7 @@
 		le32_to_cpu(itd->hw_transaction[6]),
 		le32_to_cpu(itd->hw_transaction[7]));
 	ehci_dbg (ehci,
-		"  buf:   %08x %08x %08x %08x %08x %08x %08x\n", 
+		"  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
 		le32_to_cpu(itd->hw_bufp[0]),
 		le32_to_cpu(itd->hw_bufp[1]),
 		le32_to_cpu(itd->hw_bufp[2]),
@@ -171,12 +171,12 @@
 }
 
 static void __attribute__((__unused__))
-dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) 
+dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 {
 	ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
 		label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
 	ehci_dbg (ehci,
-		"  addr %08x sched %04x result %08x buf %08x %08x\n", 
+		"  addr %08x sched %04x result %08x buf %08x %08x\n",
 		le32_to_cpu(sitd->hw_fullspeed_ep),
 		le32_to_cpu(sitd->hw_uframe),
 		le32_to_cpu(sitd->hw_results),
@@ -451,7 +451,7 @@
 	*buf = 0;
 
 	bus = class_get_devdata(class_dev);
-	hcd = bus->hcpriv;
+	hcd = bus_to_hcd(bus);
 	ehci = hcd_to_ehci (hcd);
 	next = buf;
 	size = PAGE_SIZE;
@@ -497,7 +497,7 @@
 	seen_count = 0;
 
 	bus = class_get_devdata(class_dev);
-	hcd = bus->hcpriv;
+	hcd = bus_to_hcd(bus);
 	ehci = hcd_to_ehci (hcd);
 	next = buf;
 	size = PAGE_SIZE;
@@ -634,7 +634,7 @@
 	static char		label [] = "";
 
 	bus = class_get_devdata(class_dev);
-	hcd = bus->hcpriv;
+	hcd = bus_to_hcd(bus);
 	ehci = hcd_to_ehci (hcd);
 	next = buf;
 	size = PAGE_SIZE;
@@ -754,9 +754,7 @@
 	}
 
 	if (ehci->reclaim) {
-		temp = scnprintf (next, size, "reclaim qh %p%s\n",
-				ehci->reclaim,
-				ehci->reclaim_ready ? " ready" : "");
+		temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim);
 		size -= temp;
 		next += temp;
 	}
@@ -785,10 +783,11 @@
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
 	struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
+	int retval;
 
-	class_device_create_file(cldev, &class_device_attr_async);
-	class_device_create_file(cldev, &class_device_attr_periodic);
-	class_device_create_file(cldev, &class_device_attr_registers);
+	retval = class_device_create_file(cldev, &class_device_attr_async);
+	retval = class_device_create_file(cldev, &class_device_attr_periodic);
+	retval = class_device_create_file(cldev, &class_device_attr_registers);
 }
 
 static inline void remove_debug_files (struct ehci_hcd *ehci)
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index d030516..1a915e9 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -285,6 +285,7 @@
 	.resume = ehci_bus_resume,
 #endif
 	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -329,6 +330,7 @@
 static struct platform_driver ehci_fsl_driver = {
 	.probe = ehci_fsl_drv_probe,
 	.remove = ehci_fsl_drv_remove,
+	.shutdown = usb_hcd_platform_shutdown,
 	.driver = {
 		   .name = "fsl-ehci",
 		   },
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d63177a..5ac9185 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2000-2004 by David Brownell
- * 
+ *
  * 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
@@ -70,7 +70,7 @@
  * 2002-08-06	Handling for bulk and interrupt transfers is mostly shared;
  *	only scheduling is different, no arbitrary limitations.
  * 2002-07-25	Sanity check PCI reads, mostly for better cardbus support,
- * 	clean up HC run state handshaking.
+ *	clean up HC run state handshaking.
  * 2002-05-24	Preliminary FS/LS interrupts, using scheduling shortcuts
  * 2002-05-11	Clear TT errors for FS/LS ctrl/bulk.  Fill in some other
  *	missing pieces:  enabling 64bit dma, handoff from BIOS/SMM.
@@ -111,7 +111,7 @@
 #define	EHCI_TUNE_MULT_TT	1
 #define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
 
-#define EHCI_IAA_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
+#define EHCI_IAA_MSECS		10		/* arbitrary */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
 #define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
@@ -254,6 +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);
 
 #include "ehci-hub.c"
@@ -263,6 +264,29 @@
 
 /*-------------------------------------------------------------------------*/
 
+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;
@@ -270,21 +294,9 @@
 
 	spin_lock_irqsave (&ehci->lock, flags);
 
-	/* 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 */
+	/* stop async processing after it's idled a bit */
 	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
- 		start_unlink_async (ehci, ehci->async);
+		start_unlink_async (ehci, ehci->async);
 
 	/* ehci could run by timer, without IRQs ... */
 	ehci_work (ehci, NULL);
@@ -292,21 +304,20 @@
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
-/* Reboot notifiers kick in for silicon on any bus (not just pci, etc).
+/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
  * This forcibly disables dma and IRQs, helping kexec and other cases
  * where the next system software may expect clean state.
  */
-static int
-ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
+static void
+ehci_shutdown (struct usb_hcd *hcd)
 {
-	struct ehci_hcd		*ehci;
+	struct ehci_hcd	*ehci;
 
-	ehci = container_of (self, struct ehci_hcd, reboot_notifier);
+	ehci = hcd_to_ehci (hcd);
 	(void) ehci_halt (ehci);
 
 	/* make BIOS/etc use companion controller during reboot */
 	writel (0, &ehci->regs->configured_flag);
-	return 0;
 }
 
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -334,8 +345,6 @@
 static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
-	if (ehci->reclaim_ready)
-		end_unlink_async (ehci, regs);
 
 	/* another CPU may drop ehci->lock during a schedule scan while
 	 * it reports urb completions.  this flag guards against bogus
@@ -370,6 +379,7 @@
 
 	/* 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))
@@ -381,7 +391,6 @@
 
 	/* let companion controllers work when we aren't */
 	writel (0, &ehci->regs->configured_flag);
-	unregister_reboot_notifier (&ehci->reboot_notifier);
 
 	remove_debug_files (ehci);
 
@@ -417,6 +426,10 @@
 	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.
@@ -427,13 +440,12 @@
 
 	/* controllers may cache some of the periodic schedule ... */
 	hcc_params = readl(&ehci->caps->hcc_params);
-	if (HCC_ISOC_CACHE(hcc_params)) 	// full frame cache
+	if (HCC_ISOC_CACHE(hcc_params))		// full frame cache
 		ehci->i_thresh = 8;
 	else					// N microframes cached
 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
 	ehci->reclaim = NULL;
-	ehci->reclaim_ready = 0;
 	ehci->next_uframe = -1;
 
 	/*
@@ -483,9 +495,6 @@
 	}
 	ehci->command = temp;
 
-	ehci->reboot_notifier.notifier_call = ehci_reboot;
-	register_reboot_notifier(&ehci->reboot_notifier);
-
 	return 0;
 }
 
@@ -499,7 +508,6 @@
 
 	/* EHCI spec section 4.1 */
 	if ((retval = ehci_reset(ehci)) != 0) {
-		unregister_reboot_notifier(&ehci->reboot_notifier);
 		ehci_mem_cleanup(ehci);
 		return retval;
 	}
@@ -611,7 +619,7 @@
 	/* complete the unlinking of some qh [4.15.2.3] */
 	if (status & STS_IAA) {
 		COUNT (ehci->stats.reclaim);
-		ehci->reclaim_ready = 1;
+		end_unlink_async (ehci, regs);
 		bh = 1;
 	}
 
@@ -715,10 +723,14 @@
 
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	/* if we need to use IAA and it's busy, defer */
-	if (qh->qh_state == QH_STATE_LINKED
-			&& ehci->reclaim
-			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+	// 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) {
 		struct ehci_qh		*last;
 
 		for (last = ehci->reclaim;
@@ -728,12 +740,8 @@
 		qh->qh_state = QH_STATE_UNLINK_WAIT;
 		last->reclaim = qh;
 
-	/* bypass IAA if the hc can't care */
-	} else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
-		end_unlink_async (ehci, NULL);
-
-	/* something else might have unlinked the qh by now */
-	if (qh->qh_state == QH_STATE_LINKED)
+	/* start IAA cycle */
+	} else
 		start_unlink_async (ehci, qh);
 }
 
@@ -755,7 +763,19 @@
 		qh = (struct ehci_qh *) urb->hcpriv;
 		if (!qh)
 			break;
-		unlink_async (ehci, qh);
+		switch (qh->qh_state) {
+		case QH_STATE_LINKED:
+		case QH_STATE_COMPLETING:
+			unlink_async (ehci, qh);
+			break;
+		case QH_STATE_UNLINK:
+		case QH_STATE_UNLINK_WAIT:
+			/* already started */
+			break;
+		case QH_STATE_IDLE:
+			WARN_ON(1);
+			break;
+		}
 		break;
 
 	case PIPE_INTERRUPT:
@@ -847,6 +867,7 @@
 		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 d03e3ca..b2ee13c 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 by David Brownell
- * 
+ *
  * 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
@@ -48,7 +48,7 @@
 	}
 	ehci->command = readl (&ehci->regs->command);
 	if (ehci->reclaim)
-		ehci->reclaim_ready = 1;
+		end_unlink_async (ehci, NULL);
 	ehci_work(ehci, NULL);
 
 	/* suspend any active/unsuspended ports, maybe allow wakeup */
@@ -103,10 +103,10 @@
 
 	/* re-init operational registers in case we lost power */
 	if (readl (&ehci->regs->intr_enable) == 0) {
- 		/* at least some APM implementations will try to deliver
+		/* at least some APM implementations will try to deliver
 		 * IRQs right away, so delay them until we're ready.
- 		 */
- 		intr_enable = 1;
+		 */
+		intr_enable = 1;
 		writel (0, &ehci->regs->segment);
 		writel (ehci->periodic_dma, &ehci->regs->frame_list);
 		writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
@@ -232,7 +232,7 @@
 		buf [1] = 0;
 		retval++;
 	}
-	
+
 	/* no hub change reports (bit 0) for now (power, ...) */
 
 	/* port N changes (bit N)? */
@@ -304,7 +304,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define	PORT_WAKE_BITS 	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
 static int ehci_hub_control (
 	struct usb_hcd	*hcd,
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 766061e..a8ba2e1 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001 by David Brownell
- * 
+ *
  * 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
@@ -25,7 +25,7 @@
  *	- data used only by the HCD ... kmalloc is fine
  *	- async and periodic schedules, shared by HC and HCD ... these
  *	  need to use dma_pool or dma_alloc_coherent
- *	- driver buffers, read/written by HC ... single shot DMA mapped 
+ *	- driver buffers, read/written by HC ... single shot DMA mapped
  *
  * There's also PCI "register" data, which is memory mapped.
  * No memory seen by this driver is pageable.
@@ -119,7 +119,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* The queue heads and transfer descriptors are managed from pools tied 
+/* The queue heads and transfer descriptors are managed from pools tied
  * to each of the "per device" structures.
  * This is the initialisation and cleanup code.
  */
@@ -165,7 +165,7 @@
 	int i;
 
 	/* QTDs for control/bulk/intr transfers */
-	ehci->qtd_pool = dma_pool_create ("ehci_qtd", 
+	ehci->qtd_pool = dma_pool_create ("ehci_qtd",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_qtd),
 			32 /* byte alignment (for hw parts) */,
@@ -175,7 +175,7 @@
 	}
 
 	/* QHs for control/bulk/intr transfers */
-	ehci->qh_pool = dma_pool_create ("ehci_qh", 
+	ehci->qh_pool = dma_pool_create ("ehci_qh",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_qh),
 			32 /* byte alignment (for hw parts) */,
@@ -189,7 +189,7 @@
 	}
 
 	/* ITD for high speed ISO transfers */
-	ehci->itd_pool = dma_pool_create ("ehci_itd", 
+	ehci->itd_pool = dma_pool_create ("ehci_itd",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_itd),
 			32 /* byte alignment (for hw parts) */,
@@ -199,7 +199,7 @@
 	}
 
 	/* SITD for full/low speed split ISO transfers */
-	ehci->sitd_pool = dma_pool_create ("ehci_sitd", 
+	ehci->sitd_pool = dma_pool_create ("ehci_sitd",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_sitd),
 			32 /* byte alignment (for hw parts) */,
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 6967ab7..08d0472 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -303,7 +303,7 @@
 	/* emptying the schedule aborts any urbs */
 	spin_lock_irq(&ehci->lock);
 	if (ehci->reclaim)
-		ehci->reclaim_ready = 1;
+		end_unlink_async (ehci, NULL);
 	ehci_work(ehci, NULL);
 	spin_unlock_irq(&ehci->lock);
 
@@ -338,6 +338,7 @@
 	.resume =		ehci_pci_resume,
 #endif
 	.stop =			ehci_stop,
+	.shutdown =		ehci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -384,4 +385,5 @@
 	.suspend =	usb_hcd_pci_suspend,
 	.resume =	usb_hcd_pci_resume,
 #endif
+	.shutdown = 	usb_hcd_pci_shutdown,
 };
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index e469221..7fc25b6 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 by David Brownell
- * 
+ *
  * 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,7 +31,7 @@
  * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with
  * interrupts) needs careful scheduling.  Performance improvements can be
  * an ongoing challenge.  That's in "ehci-sched.c".
- * 
+ *
  * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
  * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
  * (b) special fields in qh entries or (c) split iso entries.  TTs will
@@ -199,7 +199,7 @@
 				&& ((token & QTD_STS_MMF) != 0
 					|| QTD_CERR(token) == 0)
 				&& (!ehci_is_TDI(ehci)
-                	                || urb->dev->tt->hub !=
+			                || urb->dev->tt->hub !=
 					   ehci_to_hcd(ehci)->self.root_hub)) {
 #ifdef DEBUG
 			struct usb_device *tt = urb->dev->tt->hub;
@@ -364,7 +364,7 @@
 			 */
 			if (likely (urb->status == -EINPROGRESS))
 				continue;
-			
+
 			/* issue status after short control reads */
 			if (unlikely (do_status != 0)
 					&& QTD_PID (token) == 0 /* OUT */) {
@@ -388,7 +388,7 @@
 				wmb ();
 			}
 		}
- 
+
 		/* remove it from the queue */
 		spin_lock (&urb->lock);
 		qtd_copy_status (ehci, urb, qtd->length, token);
@@ -518,7 +518,7 @@
 		/* for zero length DATA stages, STATUS is always IN */
 		if (len == 0)
 			token |= (1 /* "in" */ << 8);
-	} 
+	}
 
 	/*
 	 * data transfer stage:  buffer setup
@@ -759,7 +759,7 @@
 		}
 		break;
 	default:
- 		dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
+		dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
 done:
 		qh_put (qh);
 		return NULL;
@@ -967,17 +967,16 @@
 	struct ehci_qh		*qh = ehci->reclaim;
 	struct ehci_qh		*next;
 
-	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
+	iaa_watchdog_done (ehci);
 
 	// qh->hw_next = cpu_to_le32 (qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
 	qh->qh_next.qh = NULL;
-	qh_put (qh);			// refcount from reclaim 
+	qh_put (qh);			// refcount from reclaim
 
 	/* 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);
@@ -1031,7 +1030,7 @@
 			timer_action_done (ehci, TIMER_ASYNC_OFF);
 		}
 		return;
-	} 
+	}
 
 	qh->qh_state = QH_STATE_UNLINK;
 	ehci->reclaim = qh = qh_get (qh);
@@ -1046,17 +1045,16 @@
 
 	if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
 		/* if (unlikely (qh->reclaim != 0))
-		 * 	this will recurse, probably not much
+		 *	this will recurse, probably not much
 		 */
 		end_unlink_async (ehci, NULL);
 		return;
 	}
 
-	ehci->reclaim_ready = 0;
 	cmd |= CMD_IAAD;
 	writel (cmd, &ehci->regs->command);
 	(void) readl (&ehci->regs->command);
-	timer_action (ehci, TIMER_IAA_WATCHDOG);
+	iaa_watchdog_start (ehci);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 4859900..e5e9c65 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2001-2004 by David Brownell
  * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers
- * 
+ *
  * 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
@@ -613,7 +613,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int check_period (
-	struct ehci_hcd *ehci, 
+	struct ehci_hcd *ehci,
 	unsigned	frame,
 	unsigned	uframe,
 	unsigned	period,
@@ -629,7 +629,7 @@
 
 	/*
 	 * 80% periodic == 100 usec/uframe available
-	 * convert "usecs we need" to "max already claimed" 
+	 * convert "usecs we need" to "max already claimed"
 	 */
 	usecs = 100 - usecs;
 
@@ -659,14 +659,14 @@
 }
 
 static int check_intr_schedule (
-	struct ehci_hcd		*ehci, 
+	struct ehci_hcd		*ehci,
 	unsigned		frame,
 	unsigned		uframe,
 	const struct ehci_qh	*qh,
 	__le32			*c_maskp
 )
 {
-    	int		retval = -ENOSPC;
+	int		retval = -ENOSPC;
 	u8		mask = 0;
 
 	if (qh->c_usecs && uframe >= 6)		/* FSTN territory? */
@@ -701,7 +701,7 @@
 	/* Make sure this tt's buffer is also available for CSPLITs.
 	 * We pessimize a bit; probably the typical full speed case
 	 * doesn't need the second CSPLIT.
-	 * 
+	 *
 	 * NOTE:  both SPLIT and CSPLIT could be checked in just
 	 * one smart pass...
 	 */
@@ -728,7 +728,7 @@
  */
 static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	int 		status;
+	int		status;
 	unsigned	uframe;
 	__le32		c_mask;
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
@@ -784,7 +784,7 @@
 		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
 
 	/* stuff into the periodic schedule */
- 	status = qh_link_periodic (ehci, qh);
+	status = qh_link_periodic (ehci, qh);
 done:
 	return status;
 }
@@ -1681,7 +1681,7 @@
 		status = -ESHUTDOWN;
 	else
 		status = iso_stream_schedule (ehci, urb, stream);
- 	if (likely (status == 0))
+	if (likely (status == 0))
 		itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -1738,7 +1738,7 @@
 		if (packet->buf1 != (buf & ~(u64)0x0fff))
 			packet->cross = 1;
 
-		/* OUT uses multiple start-splits */ 
+		/* OUT uses multiple start-splits */
 		if (stream->bEndpointAddress & USB_DIR_IN)
 			continue;
 		length = (length + 187) / 188;
@@ -1925,7 +1925,7 @@
 /*-------------------------------------------------------------------------*/
 
 #define	SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
-	       			| SITD_STS_XACT | SITD_STS_MMF)
+				| SITD_STS_XACT | SITD_STS_MMF)
 
 static unsigned
 sitd_complete (
@@ -2043,7 +2043,7 @@
 		status = -ESHUTDOWN;
 	else
 		status = iso_stream_schedule (ehci, urb, stream);
- 	if (status == 0)
+	if (status == 0)
 		sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -2226,5 +2226,5 @@
 			now_uframe++;
 			now_uframe %= mod;
 		}
-	} 
+	}
 }
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 679c1cd..6aac39f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001-2002 by David Brownell
- * 
+ *
  * 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
@@ -58,7 +58,6 @@
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
-	unsigned		reclaim_ready : 1;
 	unsigned		scanning : 1;
 
 	/* periodic schedule support */
@@ -81,8 +80,8 @@
 	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;
-	struct notifier_block	reboot_notifier;
 	unsigned long		actions;
 	unsigned		stamp;
 	unsigned long		next_statechange;
@@ -104,7 +103,7 @@
 #endif
 };
 
-/* convert between an HCD pointer and the corresponding EHCI_HCD */ 
+/* convert between an HCD pointer and the corresponding EHCI_HCD */
 static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd)
 {
 	return (struct ehci_hcd *) (hcd->hcd_priv);
@@ -115,9 +114,21 @@
 }
 
 
+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,
 };
@@ -135,9 +146,6 @@
 		unsigned long t;
 
 		switch (action) {
-		case TIMER_IAA_WATCHDOG:
-			t = EHCI_IAA_JIFFIES;
-			break;
 		case TIMER_IO_WATCHDOG:
 			t = EHCI_IO_JIFFIES;
 			break;
@@ -154,8 +162,7 @@
 		// async queue SHRINK often precedes IAA.  while it's ready
 		// to go OFF neither can matter, and afterwards the IO
 		// watchdog stops unless there's still periodic traffic.
-		if (action != TIMER_IAA_WATCHDOG
-				&& t > ehci->watchdog.expires
+		if (time_before_eq(t, ehci->watchdog.expires)
 				&& timer_pending (&ehci->watchdog))
 			return;
 		mod_timer (&ehci->watchdog, t);
@@ -179,8 +186,8 @@
 #define HCS_INDICATOR(p)	((p)&(1 << 16))	/* true: has port indicators */
 #define HCS_N_CC(p)		(((p)>>12)&0xf)	/* bits 15:12, #companion HCs */
 #define HCS_N_PCC(p)		(((p)>>8)&0xf)	/* bits 11:8, ports per CC */
-#define HCS_PORTROUTED(p)	((p)&(1 << 7))	/* true: port routing */ 
-#define HCS_PPC(p)		((p)&(1 << 4))	/* true: port power control */ 
+#define HCS_PORTROUTED(p)	((p)&(1 << 7))	/* true: port routing */
+#define HCS_PPC(p)		((p)&(1 << 4))	/* true: port power control */
 #define HCS_N_PORTS(p)		(((p)>>0)&0xf)	/* bits 3:0, ports on HC */
 
 	u32		hcc_params;      /* HCCPARAMS - offset 0x8 */
@@ -205,7 +212,7 @@
 #define CMD_LRESET	(1<<7)		/* partial reset (no ports, etc) */
 #define CMD_IAAD	(1<<6)		/* "doorbell" interrupt async advance */
 #define CMD_ASE		(1<<5)		/* async schedule enable */
-#define CMD_PSE  	(1<<4)		/* periodic schedule enable */
+#define CMD_PSE		(1<<4)		/* periodic schedule enable */
 /* 3:2 is periodic frame list size */
 #define CMD_RESET	(1<<1)		/* reset HC not bus */
 #define CMD_RUN		(1<<0)		/* start/stop HC */
@@ -231,9 +238,9 @@
 	/* FRINDEX: offset 0x0C */
 	u32		frame_index;	/* current microframe number */
 	/* CTRLDSSEGMENT: offset 0x10 */
-	u32		segment; 	/* address bits 63:32 if needed */
+	u32		segment;	/* address bits 63:32 if needed */
 	/* PERIODICLISTBASE: offset 0x14 */
-	u32		frame_list; 	/* points to periodic list */
+	u32		frame_list;	/* points to periodic list */
 	/* ASYNCLISTADDR: offset 0x18 */
 	u32		async_next;	/* address of next async queue head */
 
@@ -302,7 +309,7 @@
 
 /*
  * EHCI Specification 0.95 Section 3.5
- * QTD: describe data transfer components (buffer, direction, ...) 
+ * QTD: describe data transfer components (buffer, direction, ...)
  * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
  *
  * These are associated only with "QH" (Queue Head) structures,
@@ -312,7 +319,7 @@
 	/* first part defined by EHCI spec */
 	__le32			hw_next;	  /* see EHCI 3.5.1 */
 	__le32			hw_alt_next;      /* see EHCI 3.5.2 */
-	__le32			hw_token;         /* see EHCI 3.5.3 */       
+	__le32			hw_token;         /* see EHCI 3.5.3 */
 #define	QTD_TOGGLE	(1 << 31)	/* data toggle */
 #define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
 #define	QTD_IOC		(1 << 15)	/* interrupt on complete */
@@ -349,8 +356,8 @@
 /* values for that type tag */
 #define Q_TYPE_ITD	__constant_cpu_to_le32 (0 << 1)
 #define Q_TYPE_QH	__constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD 	__constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN 	__constant_cpu_to_le32 (3 << 1)
+#define Q_TYPE_SITD	__constant_cpu_to_le32 (2 << 1)
+#define Q_TYPE_FSTN	__constant_cpu_to_le32 (3 << 1)
 
 /* next async queue entry, or pointer to interrupt/periodic QH */
 #define	QH_NEXT(dma)	(cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
@@ -367,7 +374,7 @@
  * For entries in the async schedule, the type tag always says "qh".
  */
 union ehci_shadow {
-	struct ehci_qh 		*qh;		/* Q_TYPE_QH */
+	struct ehci_qh		*qh;		/* Q_TYPE_QH */
 	struct ehci_itd		*itd;		/* Q_TYPE_ITD */
 	struct ehci_sitd	*sitd;		/* Q_TYPE_SITD */
 	struct ehci_fstn	*fstn;		/* Q_TYPE_FSTN */
@@ -397,7 +404,7 @@
 #define	QH_HUBPORT	0x3f800000
 #define	QH_MULT		0xc0000000
 	__le32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
-	
+
 	/* qtd overlay (hardware parts of a struct ehci_qtd) */
 	__le32			hw_qtd_next;
 	__le32			hw_alt_next;
@@ -472,7 +479,7 @@
 	struct list_head	td_list;	/* queued itds/sitds */
 	struct list_head	free_list;	/* list of unused itds/sitds */
 	struct usb_device	*udev;
- 	struct usb_host_endpoint *ep;
+	struct usb_host_endpoint *ep;
 
 	/* output of (re)scheduling */
 	unsigned long		start;		/* jiffies */
@@ -492,8 +499,8 @@
 	unsigned		bandwidth;
 
 	/* This is used to initialize iTD's hw_bufp fields */
-	__le32			buf0;		
-	__le32			buf1;		
+	__le32			buf0;
+	__le32			buf1;
 	__le32			buf2;
 
 	/* this is used to initialize sITD's tt info */
@@ -521,7 +528,7 @@
 
 #define ITD_ACTIVE	__constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
 
-	__le32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
+	__le32			hw_bufp [7];	/* see EHCI 3.3.3 */
 	__le32			hw_bufp_hi [7];	/* Appendix B */
 
 	/* the rest is HCD-private */
@@ -542,7 +549,7 @@
 /*-------------------------------------------------------------------------*/
 
 /*
- * EHCI Specification 0.95 Section 3.4 
+ * EHCI Specification 0.95 Section 3.4
  * siTD, aka split-transaction isochronous Transfer Descriptor
  *       ... describe full speed iso xfers through TT in hubs
  * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 8c6b38a..a72e041 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1207,7 +1207,7 @@
 	return single_open(file, isp116x_show_dbg, inode->i_private);
 }
 
-static struct file_operations isp116x_debug_fops = {
+static const struct file_operations isp116x_debug_fops = {
 	.open = isp116x_open_seq,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index a1b7c38..b91e2ed 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -233,7 +233,7 @@
 	/* Bit Stuff  */ -EPROTO,
 	/* Data Togg  */ -EILSEQ,
 	/* Stall      */ -EPIPE,
-	/* DevNotResp */ -ETIMEDOUT,
+	/* DevNotResp */ -ETIME,
 	/* PIDCheck   */ -EPROTO,
 	/* UnExpPID   */ -EPROTO,
 	/* DataOver   */ -EOVERFLOW,
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 85cc059..b466581 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -193,7 +193,7 @@
 	if ((ret = ohci_init(ohci)) < 0)
 		return ret;
 
-	root->maxchild = board->ports;
+	ohci->num_ports = board->ports;
 
 	if ((ret = ohci_run(ohci)) < 0) {
 		err("can't start %s", hcd->self.bus_name);
@@ -221,6 +221,7 @@
 	 */
 	.start =		ohci_at91_start,
 	.stop =			ohci_stop,
+	.shutdown = 		ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -239,7 +240,7 @@
 	 */
 	.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,
@@ -296,6 +297,7 @@
 	if (!clocked) {
 		clk_enable(iclk);
 		clk_enable(fclk);
+		clocked = 1;
 	}
 
 	return 0;
@@ -310,6 +312,7 @@
 static struct platform_driver ohci_hcd_at91_driver = {
 	.probe		= ohci_hcd_at91_drv_probe,
 	.remove		= ohci_hcd_at91_drv_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
 	.suspend	= ohci_hcd_at91_drv_suspend,
 	.resume		= ohci_hcd_at91_drv_resume,
 	.driver		= {
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index f7a975d..24e23c5 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -268,11 +268,8 @@
 	 * basic lifecycle operations
 	 */
 	.start =		ohci_au1xxx_start,
-#ifdef	CONFIG_PM
-	/* suspend:		ohci_au1xxx_suspend,  -- tbd */
-	/* resume:		ohci_au1xxx_resume,   -- tbd */
-#endif /*CONFIG_PM*/
 	.stop =			ohci_stop,
+	.shutdown = 		ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -291,6 +288,7 @@
 	 */
 	.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,
@@ -338,6 +336,7 @@
 static struct platform_driver ohci_hcd_au1xxx_driver = {
 	.probe		= ohci_hcd_au1xxx_drv_probe,
 	.remove		= ohci_hcd_au1xxx_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
 	/*.suspend	= ohci_hcd_au1xxx_drv_suspend, */
 	/*.resume	= ohci_hcd_au1xxx_drv_resume, */
 	.driver		= {
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 7bfffcb..8293c1d 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -477,7 +477,7 @@
 	unsigned long		flags;
 
 	bus = class_get_devdata(class_dev);
-	hcd = bus->hcpriv;
+	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 
 	/* display control and bulk lists together, for simplicity */
@@ -510,7 +510,7 @@
 	seen_count = 0;
 
 	bus = class_get_devdata(class_dev);
-	hcd = bus->hcpriv;
+	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 	next = buf;
 	size = PAGE_SIZE;
@@ -607,7 +607,7 @@
 	u32			rdata;
 
 	bus = class_get_devdata(class_dev);
-	hcd = bus->hcpriv;
+	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 	regs = ohci->regs;
 	next = buf;
@@ -667,6 +667,11 @@
 	size -= temp;
 	next += temp;
 
+	temp = scnprintf (next, size, "hub poll timer %s\n",
+			ohci_to_hcd(ohci)->poll_rh ? "ON" : "off");
+	size -= temp;
+	next += temp;
+
 	/* roothub */
 	ohci_dump_roothub (ohci, 1, &next, &size);
 
@@ -680,10 +685,11 @@
 static inline void create_debug_files (struct ohci_hcd *ohci)
 {
 	struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
+	int retval;
 
-	class_device_create_file(cldev, &class_device_attr_async);
-	class_device_create_file(cldev, &class_device_attr_periodic);
-	class_device_create_file(cldev, &class_device_attr_registers);
+	retval = class_device_create_file(cldev, &class_device_attr_async);
+	retval = class_device_create_file(cldev, &class_device_attr_periodic);
+	retval = class_device_create_file(cldev, &class_device_attr_registers);
 	ohci_dbg (ohci, "created debug files\n");
 }
 
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 6531c4d..1bf5e7a 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -128,12 +128,14 @@
 	.flags			= HCD_USB11 | HCD_MEMORY,
 	.start			= ohci_ep93xx_start,
 	.stop			= ohci_stop,
+	.shutdown		= ohci_shutdown,
 	.urb_enqueue		= ohci_urb_enqueue,
 	.urb_dequeue		= ohci_urb_dequeue,
 	.endpoint_disable	= ohci_endpoint_disable,
 	.get_frame_number	= ohci_get_frame,
 	.hub_status_data	= ohci_hub_status_data,
 	.hub_control		= ohci_hub_control,
+	.hub_irq_enable		= ohci_rhsc_enable,
 #ifdef CONFIG_PM
 	.bus_suspend		= ohci_bus_suspend,
 	.bus_resume		= ohci_bus_resume,
@@ -202,6 +204,7 @@
 static struct platform_driver ohci_hcd_ep93xx_driver = {
 	.probe		= ohci_hcd_ep93xx_drv_probe,
 	.remove		= ohci_hcd_ep93xx_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
 	.suspend	= ohci_hcd_ep93xx_drv_suspend,
 	.resume		= ohci_hcd_ep93xx_drv_resume,
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 94d8cf4..d1d68c4 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -88,7 +88,7 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/dma-mapping.h> 
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
@@ -101,7 +101,7 @@
 
 #include "../core/hcd.h"
 
-#define DRIVER_VERSION "2005 April 22"
+#define DRIVER_VERSION "2006 August 04"
 #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
 #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
 
@@ -110,9 +110,10 @@
 #undef OHCI_VERBOSE_DEBUG	/* not always helpful */
 
 /* For initializing controller (mask in an HCFS mode too) */
-#define	OHCI_CONTROL_INIT 	OHCI_CTRL_CBSR
+#define	OHCI_CONTROL_INIT	OHCI_CTRL_CBSR
 #define	OHCI_INTR_INIT \
-	(OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
+		(OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE \
+		| OHCI_INTR_RD | OHCI_INTR_WDH)
 
 #ifdef __hppa__
 /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
@@ -128,12 +129,13 @@
 
 static const char	hcd_name [] = "ohci_hcd";
 
+#define	STATECHANGE_DELAY	msecs_to_jiffies(300)
+
 #include "ohci.h"
 
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
 static void ohci_stop (struct usb_hcd *hcd);
-static int ohci_reboot (struct notifier_block *, unsigned long , void *);
 
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
@@ -416,21 +418,20 @@
 	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
 }
 
-/* reboot notifier forcibly disables IRQs and DMA, helping kexec and
+/* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and
  * other cases where the next software may expect clean state from the
  * "firmware".  this is bus-neutral, unlike shutdown() methods.
  */
-static int
-ohci_reboot (struct notifier_block *block, unsigned long code, void *null)
+static void
+ohci_shutdown (struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci;
 
-	ohci = container_of (block, struct ohci_hcd, reboot_notifier);
+	ohci = hcd_to_ohci (hcd);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
 	ohci_usb_reset (ohci);
 	/* flush the writes */
 	(void) ohci_readl (ohci, &ohci->regs->control);
-	return 0;
 }
 
 /*-------------------------------------------------------------------------*
@@ -446,7 +447,6 @@
 
 	disable (ohci);
 	ohci->regs = hcd->regs;
-	ohci->next_statechange = jiffies;
 
 	/* REVISIT this BIOS handshake is now moved into PCI "quirks", and
 	 * was never needed for most non-PCI systems ... remove the code?
@@ -502,7 +502,6 @@
 	if ((ret = ohci_mem_init (ohci)) < 0)
 		ohci_stop (hcd);
 	else {
-		register_reboot_notifier (&ohci->reboot_notifier);
 		create_debug_files (ohci);
 	}
 
@@ -637,10 +636,14 @@
 		return -EOVERFLOW;
 	}
 
- 	/* start controller operations */
+	/* use rhsc irqs after khubd is fully initialized */
+	hcd->poll_rh = 1;
+	hcd->uses_new_polling = 1;
+
+	/* start controller operations */
 	ohci->hc_control &= OHCI_CTRL_RWC;
- 	ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
- 	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+	ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
+	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
 	hcd->state = HC_STATE_RUNNING;
 
 	/* wake on ConnectStatusChange, matching external hubs */
@@ -648,7 +651,7 @@
 
 	/* Choose the interrupts we care about now, others later on demand */
 	mask = OHCI_INTR_INIT;
-	ohci_writel (ohci, mask, &ohci->regs->intrstatus);
+	ohci_writel (ohci, ~0, &ohci->regs->intrstatus);
 	ohci_writel (ohci, mask, &ohci->regs->intrenable);
 
 	/* handle root hub init quirks ... */
@@ -672,6 +675,7 @@
 	// flush those writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
 
+	ohci->next_statechange = jiffies + STATECHANGE_DELAY;
 	spin_unlock_irq (&ohci->lock);
 
 	// POTPGT delay is bits 24-31, in 2 ms units.
@@ -709,7 +713,14 @@
 	/* interrupt for some other device? */
 	} else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
 		return IRQ_NOTMINE;
-	} 
+	}
+
+	if (ints & OHCI_INTR_RHSC) {
+		ohci_vdbg (ohci, "rhsc\n");
+		ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+		ohci_writel (ohci, OHCI_INTR_RHSC, &regs->intrstatus);
+		usb_hcd_poll_rh_status(hcd);
+	}
 
 	if (ints & OHCI_INTR_UE) {
 		disable (ohci);
@@ -723,13 +734,18 @@
 	if (ints & OHCI_INTR_RD) {
 		ohci_vdbg (ohci, "resume detect\n");
 		ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
-		if (hcd->state != HC_STATE_QUIESCING)
+		hcd->poll_rh = 1;
+		if (ohci->autostop) {
+			spin_lock (&ohci->lock);
+			ohci_rh_resume (ohci);
+			spin_unlock (&ohci->lock);
+		} else
 			usb_hcd_resume_root_hub(hcd);
 	}
 
 	if (ints & OHCI_INTR_WDH) {
 		if (HC_IS_RUNNING(hcd->state))
-			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);	
+			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
 		spin_lock (&ohci->lock);
 		dl_done_list (ohci, ptregs);
 		spin_unlock (&ohci->lock);
@@ -775,9 +791,10 @@
 
 	ohci_usb_reset (ohci);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-	
+	free_irq(hcd->irq, hcd);
+	hcd->irq = -1;
+
 	remove_debug_files (ohci);
-	unregister_reboot_notifier (&ohci->reboot_notifier);
 	ohci_mem_cleanup (ohci);
 	if (ohci->hcca) {
 		dma_free_coherent (hcd->self.controller, 
@@ -917,6 +934,10 @@
 #include "ohci-at91.c"
 #endif
 
+#ifdef CONFIG_ARCH_PNX4008
+#include "ohci-pnx4008.c"
+#endif
+
 #if !(defined(CONFIG_PCI) \
       || defined(CONFIG_SA1111) \
       || defined(CONFIG_ARCH_S3C2410) \
@@ -928,6 +949,7 @@
       || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
       || defined (CONFIG_ARCH_AT91RM9200) \
       || defined (CONFIG_ARCH_AT91SAM9261) \
+      || defined (CONFIG_ARCH_PNX4008) \
 	)
 #error "missing bus glue for ohci-hcd"
 #endif
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 5b0a23f..ec75774 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -36,27 +36,25 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef	CONFIG_PM
+/* hcd->hub_irq_enable() */
+static void ohci_rhsc_enable (struct usb_hcd *hcd)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+
+	ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+}
 
 #define OHCI_SCHED_ENABLES \
 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
 static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
 static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
-static int ohci_restart (struct ohci_hcd *ohci);
 
-static int ohci_bus_suspend (struct usb_hcd *hcd)
+static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
+__releases(ohci->lock)
+__acquires(ohci->lock)
 {
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	int			status = 0;
-	unsigned long		flags;
-
-	spin_lock_irqsave (&ohci->lock, flags);
-
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
-		spin_unlock_irqrestore (&ohci->lock, flags);
-		return -ESHUTDOWN;
-	}
 
 	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
@@ -72,15 +70,16 @@
 		ohci_dbg (ohci, "needs reinit!\n");
 		goto done;
 	case OHCI_USB_SUSPEND:
-		ohci_dbg (ohci, "already suspended\n");
-		goto done;
+		if (!ohci->autostop) {
+			ohci_dbg (ohci, "already suspended\n");
+			goto done;
+		}
 	}
-	ohci_dbg (ohci, "suspend root hub\n");
+	ohci_dbg (ohci, "%s root hub\n",
+			autostop ? "auto-stop" : "suspend");
 
 	/* First stop any processing */
-	if (ohci->hc_control & OHCI_SCHED_ENABLES) {
-		int		limit;
-
+	if (!autostop && (ohci->hc_control & OHCI_SCHED_ENABLES)) {
 		ohci->hc_control &= ~OHCI_SCHED_ENABLES;
 		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
 		ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
@@ -90,27 +89,22 @@
 		 * then the last WDH could take 6+ msec
 		 */
 		ohci_dbg (ohci, "stopping schedules ...\n");
-		limit = 2000;
-		while (limit > 0) {
-			udelay (250);
-			limit =- 250;
-			if (ohci_readl (ohci, &ohci->regs->intrstatus)
-					& OHCI_INTR_SF)
-				break;
-		}
-		dl_done_list (ohci, NULL);
-		mdelay (7);
+		ohci->autostop = 0;
+		spin_unlock_irq (&ohci->lock);
+		msleep (8);
+		spin_lock_irq (&ohci->lock);
 	}
 	dl_done_list (ohci, NULL);
 	finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
-	ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
-			&ohci->regs->intrstatus);
 
 	/* maybe resume can wake root hub */
-	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev))
+	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
+			autostop)
 		ohci->hc_control |= OHCI_CTRL_RWE;
-	else
+	else {
+		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
 		ohci->hc_control &= ~OHCI_CTRL_RWE;
+	}
 
 	/* Suspend hub ... this is the "global (to this bus) suspend" mode,
 	 * which doesn't imply ports will first be individually suspended.
@@ -121,13 +115,12 @@
 	(void) ohci_readl (ohci, &ohci->regs->control);
 
 	/* no resumes until devices finish suspending */
-	ohci->next_statechange = jiffies + msecs_to_jiffies (5);
+	if (!autostop) {
+		ohci->next_statechange = jiffies + msecs_to_jiffies (5);
+		ohci->autostop = 0;
+	}
 
 done:
-	/* external suspend vs self autosuspend ... same effect */
-	if (status == 0)
-		usb_hcd_suspend_root_hub(hcd);
-	spin_unlock_irqrestore (&ohci->lock, flags);
 	return status;
 }
 
@@ -139,25 +132,19 @@
 	return ed;
 }
 
+static int ohci_restart (struct ohci_hcd *ohci);
+
 /* caller has locked the root hub */
-static int ohci_bus_resume (struct usb_hcd *hcd)
+static int ohci_rh_resume (struct ohci_hcd *ohci)
+__releases(ohci->lock)
+__acquires(ohci->lock)
 {
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	struct usb_hcd		*hcd = ohci_to_hcd (ohci);
 	u32			temp, enables;
 	int			status = -EINPROGRESS;
-	unsigned long		flags;
+	int			autostopped = ohci->autostop;
 
-	if (time_before (jiffies, ohci->next_statechange))
-		msleep(5);
-
-	spin_lock_irqsave (&ohci->lock, flags);
-
-	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
-		spin_unlock_irqrestore (&ohci->lock, flags);
-		return -ESHUTDOWN;
-	}
-
-
+	ohci->autostop = 0;
 	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
 
 	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
@@ -177,7 +164,8 @@
 		ohci->hc_control |= OHCI_USB_RESUME;
 		ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
 		(void) ohci_readl (ohci, &ohci->regs->control);
-		ohci_dbg (ohci, "resume root hub\n");
+		ohci_dbg (ohci, "%s root hub\n",
+				autostopped ? "auto-start" : "resume");
 		break;
 	case OHCI_USB_RESUME:
 		/* HCFS changes sometime after INTR_RD */
@@ -192,16 +180,24 @@
 		ohci_dbg (ohci, "lost power\n");
 		status = -EBUSY;
 	}
-	spin_unlock_irqrestore (&ohci->lock, flags);
+#ifdef	CONFIG_PM
 	if (status == -EBUSY) {
-		(void) ohci_init (ohci);
-		return ohci_restart (ohci);
+		if (!autostopped) {
+			spin_unlock_irq (&ohci->lock);
+			(void) ohci_init (ohci);
+			status = ohci_restart (ohci);
+			spin_lock_irq (&ohci->lock);
+		}
+		return status;
 	}
+#endif
 	if (status != -EINPROGRESS)
 		return status;
+	if (autostopped)
+		goto skip_resume;
+	spin_unlock_irq (&ohci->lock);
 
 	temp = ohci->num_ports;
-	enables = 0;
 	while (temp--) {
 		u32 stat = ohci_readl (ohci,
 				       &ohci->regs->roothub.portstatus [temp]);
@@ -234,17 +230,21 @@
 	/* Sometimes PCI D3 suspend trashes frame timings ... */
 	periodic_reinit (ohci);
 
+	/* the following code is executed with ohci->lock held and
+	 * irqs disabled if and only if autostopped is true
+	 */
+
+skip_resume:
 	/* interrupts might have been disabled */
 	ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
 	if (ohci->ed_rm_list)
 		ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
-	ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
-			&ohci->regs->intrstatus);
 
 	/* Then re-enable operations */
 	ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
 	(void) ohci_readl (ohci, &ohci->regs->control);
-	msleep (3);
+	if (!autostopped)
+		msleep (3);
 
 	temp = ohci->hc_control;
 	temp &= OHCI_CTRL_RWC;
@@ -254,10 +254,14 @@
 	(void) ohci_readl (ohci, &ohci->regs->control);
 
 	/* TRSMRCY */
-	msleep (10);
+	if (!autostopped) {
+		msleep (10);
+		spin_lock_irq (&ohci->lock);
+	}
+	/* now ohci->lock is always held and irqs are always disabled */
 
-	/* keep it alive for ~5x suspend + resume costs */
-	ohci->next_statechange = jiffies + msecs_to_jiffies (250);
+	/* keep it alive for more than ~5x suspend + resume costs */
+	ohci->next_statechange = jiffies + STATECHANGE_DELAY;
 
 	/* maybe turn schedules back on */
 	enables = 0;
@@ -291,6 +295,45 @@
 	return 0;
 }
 
+#ifdef	CONFIG_PM
+
+static int ohci_bus_suspend (struct usb_hcd *hcd)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	int			rc;
+
+	spin_lock_irq (&ohci->lock);
+
+	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+		rc = -ESHUTDOWN;
+	else
+		rc = ohci_rh_suspend (ohci, 0);
+	spin_unlock_irq (&ohci->lock);
+	return rc;
+}
+
+static int ohci_bus_resume (struct usb_hcd *hcd)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	int			rc;
+
+	if (time_before (jiffies, ohci->next_statechange))
+		msleep(5);
+
+	spin_lock_irq (&ohci->lock);
+
+	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+		rc = -ESHUTDOWN;
+	else
+		rc = ohci_rh_resume (ohci);
+	spin_unlock_irq (&ohci->lock);
+
+	/* poll until we know a device is connected or we autostop */
+	if (rc == 0)
+		usb_hcd_poll_rh_status(hcd);
+	return rc;
+}
+
 #endif	/* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
@@ -302,20 +345,11 @@
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		i, changed = 0, length = 1;
-	int		can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
+	int		any_connected = 0, rhsc_enabled = 1;
 	unsigned long	flags;
 
 	spin_lock_irqsave (&ohci->lock, flags);
 
-	/* handle autosuspended root:  finish resuming before
-	 * letting khubd or root hub timer see state changes.
-	 */
-	if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
-		     || !HC_IS_RUNNING(hcd->state))) {
-		can_suspend = 0;
-		goto done;
-	}
-
 	/* undocumented erratum seen on at least rev D */
 	if ((ohci->flags & OHCI_QUIRK_AMD756)
 			&& (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
@@ -339,6 +373,9 @@
 	for (i = 0; i < ohci->num_ports; i++) {
 		u32	status = roothub_portstatus (ohci, i);
 
+		/* can't autostop if ports are connected */
+		any_connected |= (status & RH_PS_CCS);
+
 		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
 				| RH_PS_OCIC | RH_PS_PRSC)) {
 			changed = 1;
@@ -346,40 +383,73 @@
 			    buf [0] |= 1 << (i + 1);
 			else
 			    buf [1] |= 1 << (i - 7);
-			continue;
 		}
-
-		/* can suspend if no ports are enabled; or if all all
-		 * enabled ports are suspended AND remote wakeup is on.
-		 */
-		if (!(status & RH_PS_CCS))
-			continue;
-		if ((status & RH_PS_PSS) && can_suspend)
-			continue;
-		can_suspend = 0;
 	}
+
+	/* NOTE:  vendors didn't always make the same implementation
+	 * choices for RHSC.  Sometimes it triggers on an edge (like
+	 * setting and maybe clearing a port status change bit); and
+	 * it's level-triggered on other silicon, active until khubd
+	 * clears all active port status change bits.  If it's still
+	 * set (level-triggered) we must disable it and rely on
+	 * polling until khubd re-enables it.
+	 */
+	if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
+		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
+		(void) ohci_readl (ohci, &ohci->regs->intrdisable);
+		rhsc_enabled = 0;
+	}
+	hcd->poll_rh = 1;
+
+	/* carry out appropriate state changes */
+	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+
+	case OHCI_USB_OPER:
+		/* keep on polling until we know a device is connected
+		 * and RHSC is enabled */
+		if (!ohci->autostop) {
+			if (any_connected) {
+				if (rhsc_enabled)
+					hcd->poll_rh = 0;
+			} else {
+				ohci->autostop = 1;
+				ohci->next_statechange = jiffies + HZ;
+			}
+
+		/* if no devices have been attached for one second, autostop */
+		} else {
+			if (changed || any_connected) {
+				ohci->autostop = 0;
+				ohci->next_statechange = jiffies +
+						STATECHANGE_DELAY;
+			} else if (time_after_eq (jiffies,
+						ohci->next_statechange)
+					&& !ohci->ed_rm_list
+					&& !(ohci->hc_control &
+						OHCI_SCHED_ENABLES)) {
+				ohci_rh_suspend (ohci, 1);
+			}
+		}
+		break;
+
+	/* if there is a port change, autostart or ask to be resumed */
+	case OHCI_USB_SUSPEND:
+	case OHCI_USB_RESUME:
+		if (changed) {
+			if (ohci->autostop)
+				ohci_rh_resume (ohci);
+			else
+				usb_hcd_resume_root_hub (hcd);
+		} else {
+			/* everything is idle, no need for polling */
+			hcd->poll_rh = 0;
+		}
+		break;
+	}
+
 done:
 	spin_unlock_irqrestore (&ohci->lock, flags);
 
-#ifdef CONFIG_PM
-	/* save power by suspending idle root hubs;
-	 * INTR_RD wakes us when there's work
-	 */
-	if (can_suspend
-			&& !changed
-			&& !ohci->ed_rm_list
-			&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
-					& ohci->hc_control)
-				== OHCI_USB_OPER
-			&& time_after (jiffies, ohci->next_statechange)
-			&& usb_trylock_device (hcd->self.root_hub) == 0
-			) {
-		ohci_vdbg (ohci, "autosuspend\n");
-		(void) ohci_bus_suspend (hcd);
-		usb_unlock_device (hcd->self.root_hub);
-	}
-#endif
-
 	return changed ? length : 0;
 }
 
@@ -550,9 +620,6 @@
 			break;
 		case USB_PORT_FEAT_SUSPEND:
 			temp = RH_PS_POCI;
-			if ((ohci->hc_control & OHCI_CTRL_HCFS)
-					!= OHCI_USB_OPER)
-				usb_hcd_resume_root_hub(hcd);
 			break;
 		case USB_PORT_FEAT_C_SUSPEND:
 			temp = RH_PS_PSSC;
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index 5602da9..e121d97 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -173,11 +173,8 @@
 	 * basic lifecycle operations
 	 */
 	.start =		ohci_lh7a404_start,
-#ifdef	CONFIG_PM
-	/* suspend:		ohci_lh7a404_suspend,  -- tbd */
-	/* resume:		ohci_lh7a404_resume,   -- tbd */
-#endif /*CONFIG_PM*/
 	.stop =			ohci_stop,
+	.shutdown = 		ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -196,6 +193,7 @@
 	 */
 	.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,
@@ -244,6 +242,7 @@
 static struct platform_driver ohci_hcd_lh7a404_driver = {
 	.probe		= ohci_hcd_lh7a404_drv_probe,
 	.remove		= ohci_hcd_lh7a404_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
 	/*.suspend	= ohci_hcd_lh7a404_drv_suspend, */
 	/*.resume	= ohci_hcd_lh7a404_drv_resume, */
 	.driver		= {
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index bfbe328..d976614 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -28,7 +28,6 @@
 	ohci->next_statechange = jiffies;
 	spin_lock_init (&ohci->lock);
 	INIT_LIST_HEAD (&ohci->pending);
-	ohci->reboot_notifier.notifier_call = ohci_reboot;
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index c4c4bab..9c02177 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -4,7 +4,7 @@
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
  * (C) Copyright 2000-2005 David Brownell
  * (C) Copyright 2002 Hewlett-Packard Company
- * 
+ *
  * OMAP Bus Glue
  *
  * Modified for OMAP by Tony Lindgren <tony@atomide.com>
@@ -66,15 +66,20 @@
 extern int ocpi_enable(void);
 
 static struct clk *usb_host_ck;
+static struct clk *usb_dc_ck;
+static int host_enabled;
+static int host_initialized;
 
 static void omap_ohci_clock_power(int on)
 {
 	if (on) {
+		clk_enable(usb_dc_ck);
 		clk_enable(usb_host_ck);
 		/* guesstimate for T5 == 1x 32K clock + APLL lock time */
 		udelay(100);
 	} else {
 		clk_disable(usb_host_ck);
+		clk_disable(usb_dc_ck);
 	}
 }
 
@@ -87,14 +92,14 @@
 	if (on) {
 		if (machine_is_omap_innovator() && cpu_is_omap1510())
 			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
-				| ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
+				| ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
 			       INNOVATOR_FPGA_CAM_USB_CONTROL);
 		else if (machine_is_omap_osk())
 			tps65010_set_gpio_out_value(GPIO1, LOW);
 	} else {
 		if (machine_is_omap_innovator() && cpu_is_omap1510())
 			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
-				& ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
+				& ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
 			       INNOVATOR_FPGA_CAM_USB_CONTROL);
 		else if (machine_is_omap_osk())
 			tps65010_set_gpio_out_value(GPIO1, HIGH);
@@ -103,6 +108,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_ARCH_OMAP15XX
 /*
  * OMAP-1510 specific Local Bus clock on/off
  */
@@ -121,8 +127,8 @@
 /*
  * OMAP-1510 specific Local Bus initialization
  * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
- *       See also arch/mach-omap/memory.h for __virt_to_dma() and 
- *       __dma_to_virt() which need to match with the physical 
+ *       See also arch/mach-omap/memory.h for __virt_to_dma() and
+ *       __dma_to_virt() which need to match with the physical
  *       Local Bus address below.
  */
 static int omap_1510_local_bus_init(void)
@@ -130,7 +136,7 @@
 	unsigned int tlb;
 	unsigned long lbaddr, physaddr;
 
-	omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
+	omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4,
 	       OMAP1510_LB_CLOCK_DIV);
 
 	/* Configure the Local Bus MMU table */
@@ -138,7 +144,7 @@
 		lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
 		physaddr = tlb * 0x00100000 + PHYS_OFFSET;
 		omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
-		omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
+		omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc,
 		       OMAP1510_LB_MMU_CAM_L);
 		omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
 		omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
@@ -152,6 +158,10 @@
 
 	return 0;
 }
+#else
+#define omap_1510_local_bus_power(x)	{}
+#define omap_1510_local_bus_init()	{}
+#endif
 
 #ifdef	CONFIG_USB_OTG
 
@@ -173,13 +183,14 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
+static int ohci_omap_init(struct usb_hcd *hcd)
 {
-	struct omap_usb_config	*config = pdev->dev.platform_data;
+	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
+	struct omap_usb_config	*config = hcd->self.controller->platform_data;
 	int			need_transceiver = (config->otg != 0);
 	int			ret;
 
-	dev_dbg(&pdev->dev, "starting USB Controller\n");
+	dev_dbg(hcd->self.controller, "starting USB Controller\n");
 
 	if (config->otg) {
 		ohci_to_hcd(ohci)->self.otg_port = config->otg;
@@ -200,7 +211,7 @@
 		if (ohci->transceiver) {
 			int	status = otg_set_host(ohci->transceiver,
 						&ohci_to_hcd(ohci)->self);
-			dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
+			dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
 					ohci->transceiver->label, status);
 			if (status) {
 				if (ohci->transceiver)
@@ -208,7 +219,7 @@
 				return status;
 			}
 		} else {
-			dev_err(&pdev->dev, "can't find transceiver\n");
+			dev_err(hcd->self.controller, "can't find transceiver\n");
 			return -ENODEV;
 		}
 	}
@@ -247,6 +258,10 @@
 		}
 		ohci_writel(ohci, rh, &ohci->regs->roothub.a);
 		distrust_firmware = 0;
+	} else if (machine_is_nokia770()) {
+		/* We require a self-powered hub, which should have
+		 * plenty of power. */
+		ohci_to_hcd(ohci)->power_budget = 0;
 	}
 
 	/* FIXME khubd hub requests should manage power switching */
@@ -260,21 +275,15 @@
 	return 0;
 }
 
-static void omap_stop_hc(struct platform_device *pdev)
+static void ohci_omap_stop(struct usb_hcd *hcd)
 {
-	dev_dbg(&pdev->dev, "stopping USB Controller\n");
+	dev_dbg(hcd->self.controller, "stopping USB Controller\n");
 	omap_ohci_clock_power(0);
 }
 
 
 /*-------------------------------------------------------------------------*/
 
-void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
 /**
  * usb_hcd_omap_probe - initialize OMAP-based HCDs
  * Context: !in_interrupt()
@@ -283,7 +292,7 @@
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
  */
-int usb_hcd_omap_probe (const struct hc_driver *driver,
+static int usb_hcd_omap_probe (const struct hc_driver *driver,
 			  struct platform_device *pdev)
 {
 	int retval, irq;
@@ -291,12 +300,12 @@
 	struct ohci_hcd *ohci;
 
 	if (pdev->num_resources != 2) {
-		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 
+		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
 		       pdev->num_resources);
 		return -ENODEV;
 	}
 
-	if (pdev->resource[0].flags != IORESOURCE_MEM 
+	if (pdev->resource[0].flags != IORESOURCE_MEM
 			|| pdev->resource[1].flags != IORESOURCE_IRQ) {
 		printk(KERN_ERR "hcd probe: invalid resource type\n");
 		return -ENODEV;
@@ -306,6 +315,17 @@
 	if (IS_ERR(usb_host_ck))
 		return PTR_ERR(usb_host_ck);
 
+	if (!cpu_is_omap1510())
+		usb_dc_ck = clk_get(0, "usb_dc_ck");
+	else
+		usb_dc_ck = clk_get(0, "lb_ck");
+
+	if (IS_ERR(usb_dc_ck)) {
+		clk_put(usb_host_ck);
+		return PTR_ERR(usb_dc_ck);
+	}
+
+
 	hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
 	if (!hcd) {
 		retval = -ENOMEM;
@@ -325,9 +345,8 @@
 	ohci = hcd_to_ohci(hcd);
 	ohci_hcd_init(ohci);
 
-	retval = omap_start_hc(ohci, pdev);
-	if (retval < 0)
-		goto err2;
+	host_initialized = 0;
+	host_enabled = 1;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -335,15 +354,21 @@
 		goto err2;
 	}
 	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
-	if (retval == 0)
-		return retval;
+	if (retval)
+		goto err2;
 
-	omap_stop_hc(pdev);
+	host_initialized = 1;
+
+	if (!host_enabled)
+		omap_ohci_clock_power(0);
+
+	return 0;
 err2:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err1:
 	usb_put_hcd(hcd);
 err0:
+	clk_put(usb_dc_ck);
 	clk_put(usb_host_ck);
 	return retval;
 }
@@ -359,31 +384,41 @@
  * Reverses the effect of usb_hcd_omap_probe(), first invoking
  * the HCD's stop() method.  It is always called from a thread
  * context, normally "rmmod", "apmd", or something similar.
- *
  */
-void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
+static inline void
+usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+
 	usb_remove_hcd(hcd);
+	if (ohci->transceiver) {
+		(void) otg_set_host(ohci->transceiver, 0);
+		put_device(ohci->transceiver->dev);
+	}
 	if (machine_is_omap_osk())
 		omap_free_gpio(9);
-	omap_stop_hc(pdev);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
+	clk_put(usb_dc_ck);
 	clk_put(usb_host_ck);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit
+static int
 ohci_omap_start (struct usb_hcd *hcd)
 {
 	struct omap_usb_config *config;
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
+	if (!host_enabled)
+		return 0;
 	config = hcd->self.controller->platform_data;
-	if (config->otg || config->rwc)
+	if (config->otg || config->rwc) {
+		ohci->hc_control = OHCI_CTRL_RWC;
 		writel(OHCI_CTRL_RWC, &ohci->regs->control);
+	}
 
 	if ((ret = ohci_run (ohci)) < 0) {
 		dev_err(hcd->self.controller, "can't start\n");
@@ -409,8 +444,10 @@
 	/*
 	 * basic lifecycle operations
 	 */
+	.reset =		ohci_omap_init,
 	.start =		ohci_omap_start,
-	.stop =			ohci_stop,
+	.stop =			ohci_omap_stop,
+	.shutdown = 		ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -429,6 +466,7 @@
 	 */
 	.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,
@@ -446,13 +484,8 @@
 static int ohci_hcd_omap_drv_remove(struct platform_device *dev)
 {
 	struct usb_hcd		*hcd = platform_get_drvdata(dev);
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
 	usb_hcd_omap_remove(hcd, dev);
-	if (ohci->transceiver) {
-		(void) otg_set_host(ohci->transceiver, 0);
-		put_device(ohci->transceiver->dev);
-	}
 	platform_set_drvdata(dev, NULL);
 
 	return 0;
@@ -472,7 +505,7 @@
 
 	omap_ohci_clock_power(0);
 	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-	dev->power.power_state = PMSG_SUSPEND;
+	dev->dev.power.power_state = PMSG_SUSPEND;
 	return 0;
 }
 
@@ -485,8 +518,8 @@
 	ohci->next_statechange = jiffies;
 
 	omap_ohci_clock_power(1);
-	dev->power.power_state = PMSG_ON;
-	usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+	dev->dev.power.power_state = PMSG_ON;
+	usb_hcd_resume_root_hub(platform_get_drvdata(dev));
 	return 0;
 }
 
@@ -500,6 +533,7 @@
 static struct platform_driver ohci_hcd_omap_driver = {
 	.probe		= ohci_hcd_omap_drv_probe,
 	.remove		= ohci_hcd_omap_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
 #ifdef	CONFIG_PM
 	.suspend	= ohci_omap_suspend,
 	.resume		= ohci_omap_resume,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 37e1228..8744185 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -73,13 +73,14 @@
 		else if (pdev->vendor == PCI_VENDOR_ID_NS) {
 			struct pci_dev	*b;
 
-			b  = pci_find_slot (pdev->bus->number,
+			b  = pci_get_slot (pdev->bus,
 					PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
 			if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
 					&& b->vendor == PCI_VENDOR_ID_NS) {
 				ohci->flags |= OHCI_QUIRK_SUPERIO;
 				ohci_dbg (ohci, "Using NSC SuperIO setup\n");
 			}
+			pci_dev_put(b);
 		}
 
 		/* Check for Compaq's ZFMicro chipset, which needs short 
@@ -176,11 +177,14 @@
 	 */
 	.reset =		ohci_pci_reset,
 	.start =		ohci_pci_start,
+	.stop =			ohci_stop,
+	.shutdown =		ohci_shutdown,
+
 #ifdef	CONFIG_PM
+	/* these suspend/resume entries are for upstream PCI glue ONLY */
 	.suspend =		ohci_pci_suspend,
 	.resume =		ohci_pci_resume,
 #endif
-	.stop =			ohci_stop,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -199,6 +203,7 @@
 	 */
 	.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,
@@ -229,6 +234,8 @@
 	.suspend =	usb_hcd_pci_suspend,
 	.resume =	usb_hcd_pci_resume,
 #endif
+
+	.shutdown =	usb_hcd_pci_shutdown,
 };
 
  
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
new file mode 100644
index 0000000..82cb22f
--- /dev/null
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -0,0 +1,476 @@
+/*
+ * drivers/usb/host/ohci-pnx4008.c
+ *
+ * driver for Philips PNX4008 USB Host
+ *
+ * Authors: Dmitry Chigirev <source@mvista.com>
+ * 	    Vitaly Wool <vitalywool@gmail.com>
+ *
+ * register initialization is based on code examples provided by Philips
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * NOTE: This driver does not have suspend/resume functionality
+ * This driver is intended for engineering development purposes only
+ *
+ * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+
+#define USB_CTRL 	IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
+
+/* USB_CTRL bit defines */
+#define USB_SLAVE_HCLK_EN	(1 << 24)
+#define USB_HOST_NEED_CLK_EN	(1 << 21)
+
+#define USB_OTG_CLK_CTRL	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4)
+#define USB_OTG_CLK_STAT	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8)
+
+/* USB_OTG_CLK_CTRL bit defines */
+#define AHB_M_CLOCK_ON		(1 << 4)
+#define OTG_CLOCK_ON		(1 << 3)
+#define I2C_CLOCK_ON		(1 << 2)
+#define DEV_CLOCK_ON		(1 << 1)
+#define HOST_CLOCK_ON		(1 << 0)
+
+#define USB_OTG_STAT_CONTROL	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110)
+
+/* USB_OTG_STAT_CONTROL bit defines */
+#define TRANSPARENT_I2C_EN	(1 << 7)
+#define HOST_EN			(1 << 0)
+
+/* ISP1301 USB transceiver I2C registers */
+#define	ISP1301_MODE_CONTROL_1		0x04	/* u8 read, set, +1 clear */
+
+#define	MC1_SPEED_REG		(1 << 0)
+#define	MC1_SUSPEND_REG		(1 << 1)
+#define	MC1_DAT_SE0		(1 << 2)
+#define	MC1_TRANSPARENT		(1 << 3)
+#define	MC1_BDIS_ACON_EN	(1 << 4)
+#define	MC1_OE_INT_EN		(1 << 5)
+#define	MC1_UART_EN		(1 << 6)
+#define	MC1_MASK		0x7f
+
+#define	ISP1301_MODE_CONTROL_2		0x12	/* u8 read, set, +1 clear */
+
+#define	MC2_GLOBAL_PWR_DN	(1 << 0)
+#define	MC2_SPD_SUSP_CTRL	(1 << 1)
+#define	MC2_BI_DI		(1 << 2)
+#define	MC2_TRANSP_BDIR0	(1 << 3)
+#define	MC2_TRANSP_BDIR1	(1 << 4)
+#define	MC2_AUDIO_EN		(1 << 5)
+#define	MC2_PSW_EN		(1 << 6)
+#define	MC2_EN2V7		(1 << 7)
+
+#define	ISP1301_OTG_CONTROL_1		0x06	/* u8 read, set, +1 clear */
+#	define	OTG1_DP_PULLUP		(1 << 0)
+#	define	OTG1_DM_PULLUP		(1 << 1)
+#	define	OTG1_DP_PULLDOWN	(1 << 2)
+#	define	OTG1_DM_PULLDOWN	(1 << 3)
+#	define	OTG1_ID_PULLDOWN	(1 << 4)
+#	define	OTG1_VBUS_DRV		(1 << 5)
+#	define	OTG1_VBUS_DISCHRG	(1 << 6)
+#	define	OTG1_VBUS_CHRG		(1 << 7)
+#define	ISP1301_OTG_STATUS		0x10	/* u8 readonly */
+#	define	OTG_B_SESS_END		(1 << 6)
+#	define	OTG_B_SESS_VLD		(1 << 7)
+
+#define ISP1301_I2C_ADDR 0x2C
+
+#define ISP1301_I2C_MODE_CONTROL_1 0x4
+#define ISP1301_I2C_MODE_CONTROL_2 0x12
+#define ISP1301_I2C_OTG_CONTROL_1 0x6
+#define ISP1301_I2C_OTG_CONTROL_2 0x10
+#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
+#define ISP1301_I2C_INTERRUPT_LATCH 0xA
+#define ISP1301_I2C_INTERRUPT_FALLING 0xC
+#define ISP1301_I2C_INTERRUPT_RISING 0xE
+#define ISP1301_I2C_REG_CLEAR_ADDR 1
+
+struct i2c_driver isp1301_driver;
+struct i2c_client *isp1301_i2c_client;
+
+extern int usb_disabled(void);
+extern int ocpi_enable(void);
+
+static struct clk *usb_clk;
+
+static int isp1301_probe(struct i2c_adapter *adap);
+static int isp1301_detach(struct i2c_client *client);
+static int isp1301_command(struct i2c_client *client, unsigned int cmd,
+			   void *arg);
+
+static unsigned short normal_i2c[] =
+    { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
+static unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	.normal_i2c = normal_i2c,
+	.probe = dummy_i2c_addrlist,
+	.ignore = dummy_i2c_addrlist,
+};
+
+struct i2c_driver isp1301_driver = {
+	.id = I2C_DRIVERID_I2CDEV,	/* Fake Id */
+	.class = I2C_CLASS_HWMON,
+	.attach_adapter = isp1301_probe,
+	.detach_client = isp1301_detach,
+	.command = isp1301_command
+};
+
+static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct i2c_client *c;
+
+	c = (struct i2c_client *)kzalloc(sizeof(*c), SLAB_KERNEL);
+
+	if (!c)
+		return -ENOMEM;
+
+	strcpy(c->name, "isp1301");
+	c->flags = 0;
+	c->addr = addr;
+	c->adapter = adap;
+	c->driver = &isp1301_driver;
+
+	isp1301_i2c_client = c;
+
+	return i2c_attach_client(c);
+}
+
+static int isp1301_probe(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, isp1301_attach);
+}
+
+static int isp1301_detach(struct i2c_client *client)
+{
+	i2c_detach_client(client);
+	kfree(isp1301_i2c_client);
+	return 0;
+}
+
+/* No commands defined */
+static int isp1301_command(struct i2c_client *client, unsigned int cmd,
+			   void *arg)
+{
+	return 0;
+}
+
+static void i2c_write(u8 buf, u8 subaddr)
+{
+	char tmpbuf[2];
+
+	tmpbuf[0] = subaddr;	/*register number */
+	tmpbuf[1] = buf;	/*register data */
+	i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2);
+}
+
+static void isp1301_configure(void)
+{
+	/* PNX4008 only supports DAT_SE0 USB mode */
+	/* PNX4008 R2A requires setting the MAX603 to output 3.6V */
+	/* Power up externel charge-pump */
+
+	i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1);
+	i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG),
+		  ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+	i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL,
+		  ISP1301_I2C_MODE_CONTROL_2);
+	i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL),
+		  ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR);
+	i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN,
+		  ISP1301_I2C_OTG_CONTROL_1);
+	i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN),
+		  ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+	i2c_write(0xFF,
+		  ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR);
+	i2c_write(0xFF,
+		  ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR);
+	i2c_write(0xFF,
+		  ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR);
+
+}
+
+static inline void isp1301_vbus_on(void)
+{
+	i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1);
+}
+
+static inline void isp1301_vbus_off(void)
+{
+	i2c_write(OTG1_VBUS_DRV,
+		  ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+}
+
+static void pnx4008_start_hc(void)
+{
+	unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
+	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
+	isp1301_vbus_on();
+}
+
+static void pnx4008_stop_hc(void)
+{
+	unsigned long tmp;
+	isp1301_vbus_off();
+	tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN;
+	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
+}
+
+static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int ret;
+
+	if ((ret = ohci_init(ohci)) < 0)
+		return ret;
+
+	if ((ret = ohci_run(ohci)) < 0) {
+		dev_err(hcd->self.controller, "can't start\n");
+		ohci_stop(hcd);
+		return ret;
+	}
+	return 0;
+}
+
+static const struct hc_driver ohci_pnx4008_hc_driver = {
+	.description = hcd_name,
+	.product_desc =		"pnx4008 OHCI",
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ohci_irq,
+	.flags = HCD_USB11 | HCD_MEMORY,
+
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+	/*
+	 * basic lifecycle operations
+	 */
+	.start = ohci_pnx4008_start,
+	.stop = ohci_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ohci_urb_enqueue,
+	.urb_dequeue = ohci_urb_dequeue,
+	.endpoint_disable = ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ohci_hub_status_data,
+	.hub_control = ohci_hub_control,
+
+	.start_port_reset = ohci_start_port_reset,
+};
+
+#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON)
+
+static void pnx4008_set_usb_bits(void)
+{
+	start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N);
+	start_int_ack(SE_USB_OTG_ATX_INT_N);
+	start_int_umask(SE_USB_OTG_ATX_INT_N);
+
+	start_int_set_rising_edge(SE_USB_OTG_TIMER_INT);
+	start_int_ack(SE_USB_OTG_TIMER_INT);
+	start_int_umask(SE_USB_OTG_TIMER_INT);
+
+	start_int_set_rising_edge(SE_USB_I2C_INT);
+	start_int_ack(SE_USB_I2C_INT);
+	start_int_umask(SE_USB_I2C_INT);
+
+	start_int_set_rising_edge(SE_USB_INT);
+	start_int_ack(SE_USB_INT);
+	start_int_umask(SE_USB_INT);
+
+	start_int_set_rising_edge(SE_USB_NEED_CLK_INT);
+	start_int_ack(SE_USB_NEED_CLK_INT);
+	start_int_umask(SE_USB_NEED_CLK_INT);
+
+	start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT);
+	start_int_ack(SE_USB_AHB_NEED_CLK_INT);
+	start_int_umask(SE_USB_AHB_NEED_CLK_INT);
+}
+
+static void pnx4008_unset_usb_bits(void)
+{
+	start_int_mask(SE_USB_OTG_ATX_INT_N);
+	start_int_mask(SE_USB_OTG_TIMER_INT);
+	start_int_mask(SE_USB_I2C_INT);
+	start_int_mask(SE_USB_INT);
+	start_int_mask(SE_USB_NEED_CLK_INT);
+	start_int_mask(SE_USB_AHB_NEED_CLK_INT);
+}
+
+static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = 0;
+	struct ohci_hcd *ohci;
+	const struct hc_driver *driver = &ohci_pnx4008_hc_driver;
+
+	int ret = 0, irq;
+
+	dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name);
+	if (usb_disabled()) {
+		err("USB is disabled");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (pdev->num_resources != 2
+	    || pdev->resource[0].flags != IORESOURCE_MEM
+	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
+		err("Invalid resource configuration");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Enable AHB slave USB clock, needed for further USB clock control */
+	__raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
+
+	ret = i2c_add_driver(&isp1301_driver);
+	if (ret < 0) {
+		err("failed to connect I2C to ISP1301 USB Transceiver");
+		goto out;
+	}
+
+	isp1301_configure();
+
+	/* Enable USB PLL */
+	usb_clk = clk_get(&pdev->dev, "ck_pll5");
+	if (IS_ERR(usb_clk)) {
+		err("failed to acquire USB PLL");
+		ret = PTR_ERR(usb_clk);
+		goto out1;
+	}
+
+	ret = clk_enable(usb_clk);
+	if (ret < 0) {
+		err("failed to start USB PLL");
+		goto out2;
+	}
+
+	ret = clk_set_rate(usb_clk, 48000);
+	if (ret < 0) {
+		err("failed to set USB clock rate");
+		goto out3;
+	}
+
+	__raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
+
+	/* Set to enable all needed USB clocks */
+	__raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL);
+
+	while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
+	       USB_CLOCK_MASK) ;
+
+	hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+	if (!hcd) {
+		err("Failed to allocate HC buffer");
+		ret = -ENOMEM;
+		goto out3;
+	}
+
+	/* Set all USB bits in the Start Enable register */
+	pnx4008_set_usb_bits();
+
+	hcd->rsrc_start = pdev->resource[0].start;
+	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		ret =  -ENOMEM;
+		goto out4;
+	}
+	hcd->regs = (void __iomem *)pdev->resource[0].start;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = -ENXIO;
+		goto out4;
+	}
+
+	hcd->self.hcpriv = (void *)hcd;
+
+	pnx4008_start_hc();
+	platform_set_drvdata(pdev, hcd);
+	ohci = hcd_to_ohci(hcd);
+	ohci_hcd_init(ohci);
+
+	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
+	ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
+	if (ret == 0)
+		return ret;
+
+	pnx4008_stop_hc();
+out4:
+	pnx4008_unset_usb_bits();
+	usb_put_hcd(hcd);
+out3:
+	clk_disable(usb_clk);
+out2:
+	clk_put(usb_clk);
+out1:
+	i2c_del_driver(&isp1301_driver);
+out:
+	return ret;
+}
+
+static int usb_hcd_pnx4008_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	pnx4008_stop_hc();
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	pnx4008_unset_usb_bits();
+	clk_disable(usb_clk);
+	clk_put(usb_clk);
+	i2c_del_driver(&isp1301_driver);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver usb_hcd_pnx4008_driver = {
+	.driver = {
+		.name = "usb-ohci",
+	},
+	.probe = usb_hcd_pnx4008_probe,
+	.remove = usb_hcd_pnx4008_remove,
+};
+
+static int __init usb_hcd_pnx4008_init(void)
+{
+	return platform_driver_register(&usb_hcd_pnx4008_driver);
+}
+
+static void __exit usb_hcd_pnx4008_cleanup(void)
+{
+	return platform_driver_unregister(&usb_hcd_pnx4008_driver);
+}
+
+module_init(usb_hcd_pnx4008_init);
+module_exit(usb_hcd_pnx4008_cleanup);
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 9fe56ff..d9d1ae2 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -148,6 +148,7 @@
 	 */
 	.start =		ohci_ppc_soc_start,
 	.stop =			ohci_stop,
+	.shutdown = 		ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -166,6 +167,7 @@
 	 */
 	.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,
@@ -195,6 +197,7 @@
 static struct platform_driver ohci_hcd_ppc_soc_driver = {
 	.probe		= ohci_hcd_ppc_soc_drv_probe,
 	.remove		= ohci_hcd_ppc_soc_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
 #ifdef	CONFIG_PM
 	/*.suspend	= ohci_hcd_ppc_soc_drv_suspend,*/
 	/*.resume	= ohci_hcd_ppc_soc_drv_resume,*/
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 6f559e1..e176b04 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -270,6 +270,7 @@
 	 */
 	.start =		ohci_pxa27x_start,
 	.stop =			ohci_stop,
+	.shutdown = 		ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -288,6 +289,7 @@
 	 */
 	.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,
@@ -357,6 +359,7 @@
 static struct platform_driver ohci_hcd_pxa27x_driver = {
 	.probe		= ohci_hcd_pxa27x_drv_probe,
 	.remove		= ohci_hcd_pxa27x_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
 	.suspend	= ohci_hcd_pxa27x_drv_suspend, 
 	.resume		= ohci_hcd_pxa27x_drv_resume,
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index d2fc696..59e4364 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -370,7 +370,7 @@
 		goto err_mem;
 	}
 
-	usb_clk = clk_get(&dev->dev, "upll");
+	usb_clk = clk_get(&dev->dev, "usb-bus-host");
 	if (IS_ERR(usb_clk)) {
 		dev_err(&dev->dev, "cannot get usb-host clock\n");
 		retval = -ENOENT;
@@ -447,6 +447,7 @@
 	 */
 	.start =		ohci_s3c2410_start,
 	.stop =			ohci_stop,
+	.shutdown = 		ohci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -465,6 +466,7 @@
 	 */
 	.hub_status_data =	ohci_s3c2410_hub_status_data,
 	.hub_control =		ohci_s3c2410_hub_control,
+	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,
@@ -490,6 +492,7 @@
 static struct platform_driver ohci_hcd_s3c2410_driver = {
 	.probe		= ohci_hcd_s3c2410_drv_probe,
 	.remove		= ohci_hcd_s3c2410_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
 	/*.suspend	= ohci_hcd_s3c2410_drv_suspend, */
 	/*.resume	= ohci_hcd_s3c2410_drv_resume, */
 	.driver		= {
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index ce3de10..71371de 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -212,10 +212,6 @@
 	 * basic lifecycle operations
 	 */
 	.start =		ohci_sa1111_start,
-#ifdef	CONFIG_PM
-	/* suspend:		ohci_sa1111_suspend,  -- tbd */
-	/* resume:		ohci_sa1111_resume,   -- tbd */
-#endif
 	.stop =			ohci_stop,
 
 	/*
@@ -235,6 +231,7 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
+	.hub_irq_enable =	ohci_rhsc_enable,
 #ifdef	CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index caacf14..a2f42a2 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -159,7 +159,7 @@
 	/* Bit Stuff  */               -EPROTO,
 	/* Data Togg  */               -EILSEQ,
 	/* Stall      */               -EPIPE,
-	/* DevNotResp */               -ETIMEDOUT,
+	/* DevNotResp */               -ETIME,
 	/* PIDCheck   */               -EPROTO,
 	/* UnExpPID   */               -EPROTO,
 	/* DataOver   */               -EOVERFLOW,
@@ -388,8 +388,7 @@
 	u32 			hc_control;	/* copy of hc control reg */
 	unsigned long		next_statechange;	/* suspend/resume */
 	u32			fminterval;		/* saved register */
-
-	struct notifier_block	reboot_notifier;
+	unsigned		autostop:1;	/* rh auto stopping/stopped */
 
 	unsigned long		flags;		/* for HC bugs */
 #define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 9de115d9..3a586aa 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -597,7 +597,7 @@
 	/* error? retry, until "3 strikes" */
 	} else if (++ep->error_count >= 3) {
 		if (status & SL11H_STATMASK_TMOUT)
-			urbstat = -ETIMEDOUT;
+			urbstat = -ETIME;
 		else if (status & SL11H_STATMASK_OVF)
 			urbstat = -EOVERFLOW;
 		else
@@ -1517,7 +1517,7 @@
 	return single_open(file, proc_sl811h_show, PDE(inode)->data);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
 	.open		= proc_sl811h_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
new file mode 100644
index 0000000..cb2e2a6
--- /dev/null
+++ b/drivers/usb/host/u132-hcd.c
@@ -0,0 +1,3295 @@
+/*
+* Host Controller Driver for the Elan Digital Systems U132 adapter
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+* http://www.elandigitalsystems.com
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+* tony.olech@elandigitalsystems.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, version 2.
+*
+*
+* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB host drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+*/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/pci_ids.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include "../core/hcd.h"
+#include "ohci.h"
+#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+        OHCI_INTR_WDH)
+MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
+MODULE_DESCRIPTION("U132 USB Host Controller Driver");
+MODULE_LICENSE("GPL");
+#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+INT_MODULE_PARM(testing, 0);
+/* Some boards misreport power switching/overcurrent*/
+static int distrust_firmware = 1;
+module_param(distrust_firmware, bool, 0);
+MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+        "t setup");
+DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+/*
+* u132_module_lock exists to protect access to global variables
+*
+*/
+static struct semaphore u132_module_lock;
+static int u132_exiting = 0;
+static int u132_instances = 0;
+static struct list_head u132_static_list;
+/*
+* end of the global variables protected by u132_module_lock
+*/
+static struct workqueue_struct *workqueue;
+#define MAX_U132_PORTS 7
+#define MAX_U132_ADDRS 128
+#define MAX_U132_UDEVS 4
+#define MAX_U132_ENDPS 100
+#define MAX_U132_RINGS 4
+static const char *cc_to_text[16] = {
+        "No Error ",
+        "CRC Error ",
+        "Bit Stuff ",
+        "Data Togg ",
+        "Stall ",
+        "DevNotResp ",
+        "PIDCheck ",
+        "UnExpPID ",
+        "DataOver ",
+        "DataUnder ",
+        "(for hw) ",
+        "(for hw) ",
+        "BufferOver ",
+        "BuffUnder ",
+        "(for HCD) ",
+        "(for HCD) "
+};
+struct u132_port {
+        struct u132 *u132;
+        int reset;
+        int enable;
+        int power;
+        int Status;
+};
+struct u132_addr {
+        u8 address;
+};
+struct u132_udev {
+        struct kref kref;
+        struct usb_device *usb_device;
+        u8 enumeration;
+        u8 udev_number;
+        u8 usb_addr;
+        u8 portnumber;
+        u8 endp_number_in[16];
+        u8 endp_number_out[16];
+};
+#define ENDP_QUEUE_SHIFT 3
+#define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
+#define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
+struct u132_urbq {
+        struct list_head urb_more;
+        struct urb *urb;
+};
+struct u132_spin {
+        spinlock_t slock;
+};
+struct u132_endp {
+        struct kref kref;
+        u8 udev_number;
+        u8 endp_number;
+        u8 usb_addr;
+        u8 usb_endp;
+        struct u132 *u132;
+        struct list_head endp_ring;
+        struct u132_ring *ring;
+        unsigned toggle_bits:2;
+        unsigned active:1;
+        unsigned delayed:1;
+        unsigned input:1;
+        unsigned output:1;
+        unsigned pipetype:2;
+        unsigned dequeueing:1;
+        unsigned edset_flush:1;
+        unsigned spare_bits:14;
+        unsigned long jiffies;
+        struct usb_host_endpoint *hep;
+        struct u132_spin queue_lock;
+        u16 queue_size;
+        u16 queue_last;
+        u16 queue_next;
+        struct urb *urb_list[ENDP_QUEUE_SIZE];
+        struct list_head urb_more;
+        struct work_struct scheduler;
+};
+struct u132_ring {
+        unsigned in_use:1;
+        unsigned length:7;
+        u8 number;
+        struct u132 *u132;
+        struct u132_endp *curr_endp;
+        struct work_struct scheduler;
+};
+#define OHCI_QUIRK_AMD756 0x01
+#define OHCI_QUIRK_SUPERIO 0x02
+#define OHCI_QUIRK_INITRESET 0x04
+#define OHCI_BIG_ENDIAN 0x08
+#define OHCI_QUIRK_ZFMICRO 0x10
+struct u132 {
+        struct kref kref;
+        struct list_head u132_list;
+        struct semaphore sw_lock;
+        struct semaphore scheduler_lock;
+        struct u132_platform_data *board;
+        struct platform_device *platform_dev;
+        struct u132_ring ring[MAX_U132_RINGS];
+        int sequence_num;
+        int going;
+        int power;
+        int reset;
+        int num_ports;
+        u32 hc_control;
+        u32 hc_fminterval;
+        u32 hc_roothub_status;
+        u32 hc_roothub_a;
+        u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
+        int flags;
+        unsigned long next_statechange;
+        struct work_struct monitor;
+        int num_endpoints;
+        struct u132_addr addr[MAX_U132_ADDRS];
+        struct u132_udev udev[MAX_U132_UDEVS];
+        struct u132_port port[MAX_U132_PORTS];
+        struct u132_endp *endp[MAX_U132_ENDPS];
+};
+int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data);
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs,
+        u8 width, u32 *data);
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs,
+        u8 width, u32 data);
+/*
+* these can not be inlines because we need the structure offset!!
+* Does anyone have a better way?????
+*/
+#define u132_read_pcimem(u132, member, data) \
+        usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0, data);
+#define u132_write_pcimem(u132, member, data) \
+        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0, data);
+#define u132_write_pcimem_byte(u132, member, data) \
+        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0x0e, data);
+static inline struct u132 *udev_to_u132(struct u132_udev *udev)
+{
+        u8 udev_number = udev->udev_number;
+        return container_of(udev, struct u132, udev[udev_number]);
+}
+
+static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
+{
+        return (struct u132 *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
+{
+        return container_of((void *)u132, struct usb_hcd, hcd_priv);
+}
+
+static inline void u132_disable(struct u132 *u132)
+{
+        u132_to_hcd(u132)->state = HC_STATE_HALT;
+}
+
+
+#define kref_to_u132(d) container_of(d, struct u132, kref)
+#define kref_to_u132_endp(d) container_of(d, struct u132_endp, kref)
+#define kref_to_u132_udev(d) container_of(d, struct u132_udev, kref)
+#include "../misc/usb_u132.h"
+static const char hcd_name[] = "u132_hcd";
+#define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
+        USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
+        USB_PORT_STAT_C_RESET) << 16)
+static void u132_hcd_delete(struct kref *kref)
+{
+        struct u132 *u132 = kref_to_u132(kref);
+        struct platform_device *pdev = u132->platform_dev;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        u132->going += 1;
+        down(&u132_module_lock);
+        list_del_init(&u132->u132_list);
+        u132_instances -= 1;
+        up(&u132_module_lock);
+        dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
+                "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
+        usb_put_hcd(hcd);
+}
+
+static inline void u132_u132_put_kref(struct u132 *u132)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static inline void u132_u132_init_kref(struct u132 *u132)
+{
+        kref_init(&u132->kref);
+}
+
+static void u132_udev_delete(struct kref *kref)
+{
+        struct u132_udev *udev = kref_to_u132_udev(kref);
+        udev->udev_number = 0;
+        udev->usb_device = NULL;
+        udev->usb_addr = 0;
+        udev->enumeration = 0;
+}
+
+static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
+{
+        kref_put(&udev->kref, u132_udev_delete);
+}
+
+static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
+{
+        kref_get(&udev->kref);
+}
+
+static inline void u132_udev_init_kref(struct u132 *u132,
+        struct u132_udev *udev)
+{
+        kref_init(&udev->kref);
+}
+
+static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &ring->scheduler, delta))
+                        return;
+        } else if (queue_work(workqueue, &ring->scheduler))
+                return;
+        kref_put(&u132->kref, u132_hcd_delete);
+        return;
+}
+
+static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
+        unsigned int delta)
+{
+        kref_get(&u132->kref);
+        u132_ring_requeue_work(u132, ring, delta);
+        return;
+}
+
+static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
+{
+        if (cancel_delayed_work(&ring->scheduler)) {
+                kref_put(&u132->kref, u132_hcd_delete);
+        }
+}
+
+static void u132_endp_delete(struct kref *kref)
+{
+        struct u132_endp *endp = kref_to_u132_endp(kref);
+        struct u132 *u132 = endp->u132;
+        u8 usb_addr = endp->usb_addr;
+        u8 usb_endp = endp->usb_endp;
+        u8 address = u132->addr[usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        u8 endp_number = endp->endp_number;
+        struct usb_host_endpoint *hep = endp->hep;
+        struct u132_ring *ring = endp->ring;
+        struct list_head *head = &endp->endp_ring;
+        ring->length -= 1;
+        if (endp == ring->curr_endp) {
+                if (list_empty(head)) {
+                        ring->curr_endp = NULL;
+                        list_del(head);
+                } else {
+                        struct u132_endp *next_endp = list_entry(head->next,
+                                struct u132_endp, endp_ring);
+                        ring->curr_endp = next_endp;
+                        list_del(head);
+        }} else
+                list_del(head);
+        if (endp->input) {
+                udev->endp_number_in[usb_endp] = 0;
+                u132_udev_put_kref(u132, udev);
+        }
+        if (endp->output) {
+                udev->endp_number_out[usb_endp] = 0;
+                u132_udev_put_kref(u132, udev);
+        }
+        u132->endp[endp_number - 1] = NULL;
+        hep->hcpriv = NULL;
+        kfree(endp);
+        u132_u132_put_kref(u132);
+}
+
+static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
+{
+        kref_put(&endp->kref, u132_endp_delete);
+}
+
+static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
+{
+        kref_get(&endp->kref);
+}
+
+static inline void u132_endp_init_kref(struct u132 *u132,
+        struct u132_endp *endp)
+{
+        kref_init(&endp->kref);
+        kref_get(&u132->kref);
+}
+
+static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &endp->scheduler, delta))
+                        kref_get(&endp->kref);
+        } else if (queue_work(workqueue, &endp->scheduler))
+                kref_get(&endp->kref);
+        return;
+}
+
+static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
+{
+        if (cancel_delayed_work(&endp->scheduler))
+                kref_put(&endp->kref, u132_endp_delete);
+}
+
+static inline void u132_monitor_put_kref(struct u132 *u132)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &u132->monitor, delta)) {
+                        kref_get(&u132->kref);
+                }
+        } else if (queue_work(workqueue, &u132->monitor))
+                kref_get(&u132->kref);
+        return;
+}
+
+static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &u132->monitor, delta))
+                        return;
+        } else if (queue_work(workqueue, &u132->monitor))
+                return;
+        kref_put(&u132->kref, u132_hcd_delete);
+        return;
+}
+
+static void u132_monitor_cancel_work(struct u132 *u132)
+{
+        if (cancel_delayed_work(&u132->monitor))
+                kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static int read_roothub_info(struct u132 *u132)
+{
+        u32 revision;
+        int retval;
+        retval = u132_read_pcimem(u132, revision, &revision);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                        "ntrol\n", retval);
+                return retval;
+        } else if ((revision & 0xFF) == 0x10) {
+        } else if ((revision & 0xFF) == 0x11) {
+        } else {
+                dev_err(&u132->platform_dev->dev, "device revision is not valid"
+                        " %08X\n", revision);
+                return -ENODEV;
+        }
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                        "ntrol\n", retval);
+                return retval;
+        }
+        retval = u132_read_pcimem(u132, roothub.status,
+                &u132->hc_roothub_status);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                        "g roothub.status\n", retval);
+                return retval;
+        }
+        retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                        "g roothub.a\n", retval);
+                return retval;
+        }
+        {
+                int I = u132->num_ports;
+                int i = 0;
+                while (I-- > 0) {
+                        retval = u132_read_pcimem(u132, roothub.portstatus[i],
+                                &u132->hc_roothub_portstatus[i]);
+                        if (retval) {
+                                dev_err(&u132->platform_dev->dev, "error %d acc"
+                                        "essing device roothub.portstatus[%d]\n"
+                                        , retval, i);
+                                return retval;
+                        } else
+                                i += 1;
+                }
+        }
+        return 0;
+}
+
+static void u132_hcd_monitor_work(void *data)
+{
+        struct u132 *u132 = data;
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                u132_monitor_put_kref(u132);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                u132_monitor_put_kref(u132);
+                return;
+        } else {
+                int retval;
+                down(&u132->sw_lock);
+                retval = read_roothub_info(u132);
+                if (retval) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        u132_disable(u132);
+                        u132->going = 1;
+                        up(&u132->sw_lock);
+                        usb_hc_died(hcd);
+                        ftdi_elan_gone_away(u132->platform_dev);
+                        u132_monitor_put_kref(u132);
+                        return;
+                } else {
+                        u132_monitor_requeue_work(u132, 500);
+                        up(&u132->sw_lock);
+                        return;
+                }
+        }
+}
+
+static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        struct u132_ring *ring;
+        unsigned long irqs;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        urb->error_count = 0;
+        urb->status = status;
+        urb->hcpriv = NULL;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->queue_next += 1;
+        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        } else {
+                struct list_head *next = endp->urb_more.next;
+                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                        urb_more);
+                list_del(next);
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                        urbq->urb;
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                kfree(urbq);
+        } down(&u132->scheduler_lock);
+        ring = endp->ring;
+        ring->in_use = 0;
+        u132_ring_cancel_work(u132, ring);
+        u132_ring_queue_work(u132, ring, 0);
+        up(&u132->scheduler_lock);
+        u132_endp_put_kref(u132, endp);
+        usb_hcd_giveback_urb(hcd, urb, NULL);
+        return;
+}
+
+static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        u132_endp_put_kref(u132, endp);
+}
+
+static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        unsigned long irqs;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        urb->error_count = 0;
+        urb->status = status;
+        urb->hcpriv = NULL;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->queue_next += 1;
+        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        } else {
+                struct list_head *next = endp->urb_more.next;
+                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                        urb_more);
+                list_del(next);
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                        urbq->urb;
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                kfree(urbq);
+        } usb_hcd_giveback_urb(hcd, urb, NULL);
+        return;
+}
+
+static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
+                 urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
+                 urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
+                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
+                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+
+/*
+* must not LOCK sw_lock
+*
+*/
+static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer + urb->actual_length;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length += len;
+                if ((condition_code == TD_CC_NOERROR) &&
+                        (urb->transfer_buffer_length > urb->actual_length)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        if (urb->actual_length > 0) {
+                                int retval;
+                                up(&u132->scheduler_lock);
+                                retval = edset_single(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_interrupt_recv);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                        } else {
+                                ring->in_use = 0;
+                                endp->active = 0;
+                                endp->jiffies = jiffies +
+                                        msecs_to_jiffies(urb->interval);
+                                u132_ring_cancel_work(u132, ring);
+                                u132_ring_queue_work(u132, ring, 0);
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                        }
+                        return;
+                } else if ((condition_code == TD_DATAUNDERRUN) &&
+                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else {
+                        if (condition_code == TD_CC_NOERROR) {
+                                endp->toggle_bits = toggle_bits;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 1 & toggle_bits);
+                        } else if (condition_code == TD_CC_STALL) {
+                                endp->toggle_bits = 0x2;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 0);
+                        } else {
+                                endp->toggle_bits = 0x2;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 0);
+                                dev_err(&u132->platform_dev->dev, "urb=%p givin"
+                                        "g back INTERRUPT %s\n", urb,
+                                        cc_to_text[condition_code]);
+                        }
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                urb->actual_length += len;
+                endp->toggle_bits = toggle_bits;
+                if (urb->transfer_buffer_length > urb->actual_length) {
+                        int retval;
+                        up(&u132->scheduler_lock);
+                        retval = edset_output(u132, ring, endp, urb, address,
+                                endp->toggle_bits, u132_hcd_bulk_output_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer + urb->actual_length;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length += len;
+                if ((condition_code == TD_CC_NOERROR) &&
+                        (urb->transfer_buffer_length > urb->actual_length)) {
+                        int retval;
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, endp->toggle_bits,
+                                u132_hcd_bulk_input_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (condition_code == TD_CC_NOERROR) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else if ((condition_code == TD_DATAUNDERRUN) &&
+                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else if (condition_code == TD_DATAUNDERRUN) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
+                                ") giving back BULK IN %s\n", urb,
+                                cc_to_text[condition_code]);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else if (condition_code == TD_CC_STALL) {
+                        endp->toggle_bits = 0x2;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else {
+                        endp->toggle_bits = 0x2;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                        dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
+                                "ULK IN code=%d %s\n", urb, condition_code,
+                                cc_to_text[condition_code]);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length = len;
+                if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
+                        TD_DATAUNDERRUN) && ((urb->transfer_flags &
+                        URB_SHORT_NOT_OK) == 0))) {
+                        int retval;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0x3,
+                                u132_hcd_configure_empty_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (condition_code == TD_CC_STALL) {
+                        up(&u132->scheduler_lock);
+                        dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
+                                "NPUT STALL urb %p\n", urb);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
+                                "PUT %s urb %p\n", cc_to_text[condition_code],
+                                urb);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                if (usb_pipein(urb->pipe)) {
+                        int retval;
+                        struct u132_ring *ring = endp->ring;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0,
+                                u132_hcd_configure_input_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        int retval;
+                        struct u132_ring *ring = endp->ring;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0,
+                                u132_hcd_configure_empty_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
+        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                u132->addr[0].address = 0;
+                endp->usb_addr = udev->usb_addr;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                        ring->number, endp, urb, 0, endp->usb_endp, 0,
+                        u132_hcd_enumeration_empty_recv);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length = len;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                        ring->number, endp, urb, address, endp->usb_endp, 0x3,
+                        u132_hcd_initial_empty_sent);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                        ring->number, endp, urb, address, endp->usb_endp, 0,
+                        u132_hcd_initial_input_recv);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_ring_work_scheduler(void *data);
+static void u132_hcd_endp_work_scheduler(void *data);
+/*
+* this work function is only executed from the work queue
+*
+*/
+static void u132_hcd_ring_work_scheduler(void *data)
+{
+        struct u132_ring *ring = data;
+        struct u132 *u132 = ring->u132;
+        down(&u132->scheduler_lock);
+        if (ring->in_use) {
+                up(&u132->scheduler_lock);
+                u132_ring_put_kref(u132, ring);
+                return;
+        } else if (ring->curr_endp) {
+                struct u132_endp *last_endp = ring->curr_endp;
+                struct list_head *scan;
+                struct list_head *head = &last_endp->endp_ring;
+                unsigned long wakeup = 0;
+                list_for_each(scan, head) {
+                        struct u132_endp *endp = list_entry(scan,
+                                struct u132_endp, endp_ring);
+                        if (endp->queue_next == endp->queue_last) {
+                        } else if ((endp->delayed == 0)
+                                || time_after_eq(jiffies, endp->jiffies)) {
+                                ring->curr_endp = endp;
+                                u132_endp_cancel_work(u132, last_endp);
+                                u132_endp_queue_work(u132, last_endp, 0);
+                                up(&u132->scheduler_lock);
+                                u132_ring_put_kref(u132, ring);
+                                return;
+                        } else {
+                                unsigned long delta = endp->jiffies - jiffies;
+                                if (delta > wakeup)
+                                        wakeup = delta;
+                        }
+                }
+                if (last_endp->queue_next == last_endp->queue_last) {
+                } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
+                        last_endp->jiffies)) {
+                        u132_endp_cancel_work(u132, last_endp);
+                        u132_endp_queue_work(u132, last_endp, 0);
+                        up(&u132->scheduler_lock);
+                        u132_ring_put_kref(u132, ring);
+                        return;
+                } else {
+                        unsigned long delta = last_endp->jiffies - jiffies;
+                        if (delta > wakeup)
+                                wakeup = delta;
+                }
+                if (wakeup > 0) {
+                        u132_ring_requeue_work(u132, ring, wakeup);
+                        up(&u132->scheduler_lock);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        u132_ring_put_kref(u132, ring);
+                        return;
+                }
+        } else {
+                up(&u132->scheduler_lock);
+                u132_ring_put_kref(u132, ring);
+                return;
+        }
+}
+
+static void u132_hcd_endp_work_scheduler(void *data)
+{
+        struct u132_ring *ring;
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        ring = endp->ring;
+        if (endp->edset_flush) {
+                endp->edset_flush = 0;
+                if (endp->dequeueing)
+                        usb_ftdi_elan_edset_flush(u132->platform_dev,
+                                ring->number, endp);
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->active) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (ring->in_use) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->queue_next == endp->queue_last) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->pipetype == PIPE_INTERRUPT) {
+                u8 address = u132->addr[endp->usb_addr].address;
+                if (ring->in_use) {
+                        up(&u132->scheduler_lock);
+                        u132_endp_put_kref(u132, endp);
+                        return;
+                } else {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_single(u132, ring, endp, urb, address,
+                                endp->toggle_bits, u132_hcd_interrupt_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else if (endp->pipetype == PIPE_CONTROL) {
+                u8 address = u132->addr[endp->usb_addr].address;
+                if (ring->in_use) {
+                        up(&u132->scheduler_lock);
+                        u132_endp_put_kref(u132, endp);
+                        return;
+                } else if (address == 0) {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, address,
+                                0x2, u132_hcd_initial_setup_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (endp->usb_addr == 0) {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
+                                u132_hcd_enumeration_address_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        int retval;
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, address,
+                                0x2, u132_hcd_configure_setup_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else {
+                if (endp->input) {
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        if (ring->in_use) {
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                                return;
+                        } else {
+                                int retval;
+                                struct urb *urb = endp->urb_list[
+                                        ENDP_QUEUE_MASK & endp->queue_next];
+                                endp->active = 1;
+                                ring->curr_endp = endp;
+                                ring->in_use = 1;
+                                up(&u132->scheduler_lock);
+                                retval = edset_input(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_bulk_input_recv);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                                return;
+                        }
+                } else {        /* output pipe */
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        if (ring->in_use) {
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                                return;
+                        } else {
+                                int retval;
+                                struct urb *urb = endp->urb_list[
+                                        ENDP_QUEUE_MASK & endp->queue_next];
+                                endp->active = 1;
+                                ring->curr_endp = endp;
+                                ring->in_use = 1;
+                                up(&u132->scheduler_lock);
+                                retval = edset_output(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_bulk_output_sent);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                                return;
+                        }
+                }
+        }
+}
+
+static void port_power(struct u132 *u132, int pn, int is_on)
+{
+        u132->port[pn].power = is_on;
+}
+
+static void u132_power(struct u132 *u132, int is_on)
+{
+        struct usb_hcd *hcd = u132_to_hcd(u132)
+                ;        /* hub is inactive unless the port is powered */
+        if (is_on) {
+                if (u132->power)
+                        return;
+                u132->power = 1;
+                hcd->self.controller->power.power_state = PMSG_ON;
+        } else {
+                u132->power = 0;
+                hcd->state = HC_STATE_HALT;
+                hcd->self.controller->power.power_state = PMSG_SUSPEND;
+        }
+}
+
+static int u132_periodic_reinit(struct u132 *u132)
+{
+        int retval;
+        u32 fi = u132->hc_fminterval & 0x03fff;
+        u32 fit;
+        u32 fminterval;
+        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+        if (retval)
+                return retval;
+        fit = fminterval & FIT;
+        retval = u132_write_pcimem(u132, fminterval,
+                (fit ^ FIT) | u132->hc_fminterval);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, periodicstart,
+                ((9 *fi) / 10) & 0x3fff);
+        if (retval)
+                return retval;
+        return 0;
+}
+
+static char *hcfs2string(int state)
+{
+        switch (state) {
+        case OHCI_USB_RESET:
+                return "reset";
+        case OHCI_USB_RESUME:
+                return "resume";
+        case OHCI_USB_OPER:
+                return "operational";
+        case OHCI_USB_SUSPEND:
+                return "suspend";
+        }
+        return "?";
+}
+
+static int u132_usb_reset(struct u132 *u132)
+{
+        int retval;
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval)
+                return retval;
+        u132->hc_control &= OHCI_CTRL_RWC;
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        return 0;
+}
+
+static int u132_init(struct u132 *u132)
+{
+        int retval;
+        u32 control;
+        u132_disable(u132);
+        u132->next_statechange =
+                jiffies; /* SMM owns the HC? not for long! */  {
+                u32 control;
+                retval = u132_read_pcimem(u132, control, &control);
+                if (retval)
+                        return retval;
+                if (control & OHCI_CTRL_IR) {
+                        u32 temp = 50;
+                        retval = u132_write_pcimem(u132, intrenable,
+                                OHCI_INTR_OC);
+                        if (retval)
+                                return retval;
+                        retval = u132_write_pcimem_byte(u132, cmdstatus,
+                                OHCI_OCR);
+                        if (retval)
+                                return retval;
+                      check:{
+                                retval = u132_read_pcimem(u132, control,
+                                        &control);
+                                if (retval)
+                                        return retval;
+                        }
+                        if (control & OHCI_CTRL_IR) {
+                                msleep(10);
+                                if (--temp == 0) {
+                                        dev_err(&u132->platform_dev->dev, "USB "
+                                                "HC takeover failed!(BIOS/SMM b"
+                                                "ug) control=%08X\n", control);
+                                        return -EBUSY;
+                                }
+                                goto check;
+                        }
+                        u132_usb_reset(u132);
+                }
+        }
+        retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        if (u132->num_ports == 0) {
+                u32 rh_a = -1;
+                retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+                if (retval)
+                        return retval;
+                u132->num_ports = rh_a & RH_A_NDP;
+                retval = read_roothub_info(u132);
+                if (retval)
+                        return retval;
+        }
+        if (u132->num_ports > MAX_U132_PORTS) {
+                return -EINVAL;
+        }
+        return 0;
+}
+
+
+/* Start an OHCI controller, set the BUS operational
+* resets USB and controller
+* enable interrupts
+*/
+static int u132_run(struct u132 *u132)
+{
+        int retval;
+        u32 control;
+        u32 status;
+        u32 fminterval;
+        u32 periodicstart;
+        u32 cmdstatus;
+        u32 roothub_a;
+        int mask = OHCI_INTR_INIT;
+        int first = u132->hc_fminterval == 0;
+        int sleep_time = 0;
+        int reset_timeout = 30;        /* ... allow extra time */
+        u132_disable(u132);
+        if (first) {
+                u32 temp;
+                retval = u132_read_pcimem(u132, fminterval, &temp);
+                if (retval)
+                        return retval;
+                u132->hc_fminterval = temp & 0x3fff;
+                if (u132->hc_fminterval != FI) {
+                }
+                u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
+        }
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval)
+                return retval;
+        dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
+                "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
+                u132->hc_control);
+        switch (u132->hc_control & OHCI_CTRL_HCFS) {
+        case OHCI_USB_OPER:
+                sleep_time = 0;
+                break;
+        case OHCI_USB_SUSPEND:
+        case OHCI_USB_RESUME:
+                u132->hc_control &= OHCI_CTRL_RWC;
+                u132->hc_control |= OHCI_USB_RESUME;
+                sleep_time = 10;
+                break;
+        default:
+                u132->hc_control &= OHCI_CTRL_RWC;
+                u132->hc_control |= OHCI_USB_RESET;
+                sleep_time = 50;
+                break;
+        }
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        msleep(sleep_time);
+        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+        if (retval)
+                return retval;
+        if (!(roothub_a & RH_A_NPS)) {
+                int temp;        /* power down each port */
+                for (temp = 0; temp < u132->num_ports; temp++) {
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[temp], RH_PS_LSDA);
+                        if (retval)
+                                return retval;
+                }
+        }
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+      retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR);
+        if (retval)
+                return retval;
+      extra:{
+                retval = u132_read_pcimem(u132, cmdstatus, &status);
+                if (retval)
+                        return retval;
+                if (0 != (status & OHCI_HCR)) {
+                        if (--reset_timeout == 0) {
+                                dev_err(&u132->platform_dev->dev, "USB HC reset"
+                                        " timed out!\n");
+                                return -ENODEV;
+                        } else {
+                                msleep(5);
+                                goto extra;
+                        }
+                }
+        }
+        if (u132->flags & OHCI_QUIRK_INITRESET) {
+                retval = u132_write_pcimem(u132, control, u132->hc_control);
+                if (retval)
+                        return retval;
+                retval = u132_read_pcimem(u132, control, &control);
+                if (retval)
+                        return retval;
+        }
+        retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, hcca, 0x00000000);
+        if (retval)
+                return retval;
+        retval = u132_periodic_reinit(u132);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
+        if (retval)
+                return retval;
+        if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+                if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
+                        u132->flags |= OHCI_QUIRK_INITRESET;
+                        goto retry;
+                } else
+                        dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
+                                "\n", fminterval, periodicstart);
+        }                        /* start controller operations */
+        u132->hc_control &= OHCI_CTRL_RWC;
+        u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+        retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, intrstatus, mask);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, intrdisable,
+                OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+                OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+                OHCI_INTR_SO);
+        if (retval)
+                return retval;        /* handle root hub init quirks ... */
+        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+        if (retval)
+                return retval;
+        roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+        if (u132->flags & OHCI_QUIRK_SUPERIO) {
+                roothub_a |= RH_A_NOCP;
+                roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+                if (retval)
+                        return retval;
+        } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
+                roothub_a |= RH_A_NPS;
+                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+                if (retval)
+                        return retval;
+        }
+        retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, roothub.b,
+                (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        mdelay((roothub_a >> 23) & 0x1fe);
+        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+        return 0;
+}
+
+static void u132_hcd_stop(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                        "ed\n", hcd);
+        } else {
+                down(&u132->sw_lock);
+                msleep(100);
+                u132_power(u132, 0);
+                up(&u132->sw_lock);
+        }
+}
+
+static int u132_hcd_start(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else if (hcd->self.controller) {
+                int retval;
+                struct platform_device *pdev =
+                        to_platform_device(hcd->self.controller);
+                u16 vendor = ((struct u132_platform_data *)
+                        (pdev->dev.platform_data))->vendor;
+                u16 device = ((struct u132_platform_data *)
+                        (pdev->dev.platform_data))->device;
+                down(&u132->sw_lock);
+                msleep(10);
+                if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
+                        u132->flags = OHCI_QUIRK_AMD756;
+                } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
+                        dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
+                                "ounds unavailable\n");
+                } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
+                        u132->flags |= OHCI_QUIRK_ZFMICRO;
+                retval = u132_run(u132);
+                if (retval) {
+                        u132_disable(u132);
+                        u132->going = 1;
+                }
+                msleep(100);
+                up(&u132->sw_lock);
+                return retval;
+        } else {
+                dev_err(&u132->platform_dev->dev, "platform_device missing\n");
+                return -ENODEV;
+        }
+}
+
+static int u132_hcd_reset(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval;
+                down(&u132->sw_lock);
+                retval = u132_init(u132);
+                if (retval) {
+                        u132_disable(u132);
+                        u132->going = 1;
+                }
+                up(&u132->sw_lock);
+                return retval;
+        }
+}
+
+static int create_endpoint_and_queue_int(struct u132 *u132,
+        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+        gfp_t mem_flags)
+{
+        struct u132_ring *ring;
+        unsigned long irqs;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        ring = endp->ring = &u132->ring[0];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        endp->pipetype = usb_pipetype(urb->pipe);
+        u132_endp_init_kref(u132, endp);
+        if (usb_pipein(urb->pipe)) {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+                endp->input = 1;
+                endp->output = 0;
+                udev->endp_number_in[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        } else {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+                endp->input = 0;
+                endp->output = 1;
+                udev->endp_number_out[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        }
+        urb->hcpriv = u132;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->delayed = 1;
+        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+        endp->udev_number = address;
+        endp->usb_addr = usb_addr;
+        endp->usb_endp = usb_endp;
+        endp->queue_size = 1;
+        endp->queue_last = 0;
+        endp->queue_next = 0;
+        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
+        return 0;
+}
+
+static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp, u8 address)
+{
+        urb->hcpriv = u132;
+        endp->delayed = 1;
+        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        } else {
+                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                        GFP_ATOMIC);
+                if (urbq == NULL) {
+                        endp->queue_size -= 1;
+                        return -ENOMEM;
+                } else {
+                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+                        urbq->urb = urb;
+                }
+        }
+        return 0;
+}
+
+static int create_endpoint_and_queue_bulk(struct u132 *u132,
+        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+        gfp_t mem_flags)
+{
+        int ring_number;
+        struct u132_ring *ring;
+        unsigned long irqs;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        endp->pipetype = usb_pipetype(urb->pipe);
+        u132_endp_init_kref(u132, endp);
+        if (usb_pipein(urb->pipe)) {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+                ring_number = 3;
+                endp->input = 1;
+                endp->output = 0;
+                udev->endp_number_in[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        } else {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+                ring_number = 2;
+                endp->input = 0;
+                endp->output = 1;
+                udev->endp_number_out[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        }
+        ring = endp->ring = &u132->ring[ring_number - 1];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        urb->hcpriv = u132;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->udev_number = address;
+        endp->usb_addr = usb_addr;
+        endp->usb_endp = usb_endp;
+        endp->queue_size = 1;
+        endp->queue_last = 0;
+        endp->queue_next = 0;
+        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        u132_endp_queue_work(u132, endp, 0);
+        return 0;
+}
+
+static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+         struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp, u8 address)
+{
+        urb->hcpriv = u132;
+        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        } else {
+                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                        GFP_ATOMIC);
+                if (urbq == NULL) {
+                        endp->queue_size -= 1;
+                        return -ENOMEM;
+                } else {
+                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+                        urbq->urb = urb;
+                }
+        }
+        return 0;
+}
+
+static int create_endpoint_and_queue_control(struct u132 *u132,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
+        gfp_t mem_flags)
+{
+        struct u132_ring *ring;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        ring = endp->ring = &u132->ring[0];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        u132_endp_init_kref(u132, endp);
+        u132_endp_get_kref(u132, endp);
+        if (usb_addr == 0) {
+                unsigned long irqs;
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                endp->udev_number = address;
+                endp->usb_addr = usb_addr;
+                endp->usb_endp = usb_endp;
+                endp->input = 1;
+                endp->output = 1;
+                endp->pipetype = usb_pipetype(urb->pipe);
+                u132_udev_init_kref(u132, udev);
+                u132_udev_get_kref(u132, udev);
+                udev->endp_number_in[usb_endp] = endp_number;
+                udev->endp_number_out[usb_endp] = endp_number;
+                urb->hcpriv = u132;
+                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                endp->queue_size = 1;
+                endp->queue_last = 0;
+                endp->queue_next = 0;
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                u132_endp_queue_work(u132, endp, 0);
+                return 0;
+        } else {                /*(usb_addr > 0) */
+                unsigned long irqs;
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                endp->udev_number = address;
+                endp->usb_addr = usb_addr;
+                endp->usb_endp = usb_endp;
+                endp->input = 1;
+                endp->output = 1;
+                endp->pipetype = usb_pipetype(urb->pipe);
+                u132_udev_get_kref(u132, udev);
+                udev->enumeration = 2;
+                udev->endp_number_in[usb_endp] = endp_number;
+                udev->endp_number_out[usb_endp] = endp_number;
+                urb->hcpriv = u132;
+                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                endp->queue_size = 1;
+                endp->queue_last = 0;
+                endp->queue_next = 0;
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                u132_endp_queue_work(u132, endp, 0);
+                return 0;
+        }
+}
+
+static int queue_control_on_old_endpoint(struct u132 *u132,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp)
+{
+        if (usb_addr == 0) {
+                if (usb_pipein(urb->pipe)) {
+                        urb->hcpriv = u132;
+                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                                endp->urb_list[ENDP_QUEUE_MASK &
+                                        endp->queue_last++] = urb;
+                        } else {
+                                struct u132_urbq *urbq =
+                                        kmalloc(sizeof(struct u132_urbq),
+                                        GFP_ATOMIC);
+                                if (urbq == NULL) {
+                                        endp->queue_size -= 1;
+                                        return -ENOMEM;
+                                } else {
+                                        list_add_tail(&urbq->urb_more,
+                                                &endp->urb_more);
+                                        urbq->urb = urb;
+                                }
+                        }
+                        return 0;
+                } else {        /* usb_pipeout(urb->pipe) */
+                        struct u132_addr *addr = &u132->addr[usb_dev->devnum];
+                        int I = MAX_U132_UDEVS;
+                        int i = 0;
+                        while (--I > 0) {
+                                struct u132_udev *udev = &u132->udev[++i];
+                                if (udev->usb_device) {
+                                        continue;
+                                } else {
+                                        udev->enumeration = 1;
+                                        u132->addr[0].address = i;
+                                        endp->udev_number = i;
+                                        udev->udev_number = i;
+                                        udev->usb_addr = usb_dev->devnum;
+                                        u132_udev_init_kref(u132, udev);
+                                        udev->endp_number_in[usb_endp] =
+                                                endp->endp_number;
+                                        u132_udev_get_kref(u132, udev);
+                                        udev->endp_number_out[usb_endp] =
+                                                endp->endp_number;
+                                        udev->usb_device = usb_dev;
+                                        ((u8 *) (urb->setup_packet))[2] =
+                                                addr->address = i;
+                                        u132_udev_get_kref(u132, udev);
+                                        break;
+                                }
+                        }
+                        if (I == 0) {
+                                dev_err(&u132->platform_dev->dev, "run out of d"
+                                        "evice space\n");
+                                return -EINVAL;
+                        }
+                        urb->hcpriv = u132;
+                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                                endp->urb_list[ENDP_QUEUE_MASK &
+                                        endp->queue_last++] = urb;
+                        } else {
+                                struct u132_urbq *urbq =
+                                        kmalloc(sizeof(struct u132_urbq),
+                                        GFP_ATOMIC);
+                                if (urbq == NULL) {
+                                        endp->queue_size -= 1;
+                                        return -ENOMEM;
+                                } else {
+                                        list_add_tail(&urbq->urb_more,
+                                                &endp->urb_more);
+                                        urbq->urb = urb;
+                                }
+                        }
+                        return 0;
+                }
+        } else {                /*(usb_addr > 0) */
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                urb->hcpriv = u132;
+                if (udev->enumeration == 2) {
+                } else
+                        udev->enumeration = 2;
+                if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                                urb;
+                } else {
+                        struct u132_urbq *urbq =
+                                kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
+                        if (urbq == NULL) {
+                                endp->queue_size -= 1;
+                                return -ENOMEM;
+                        } else {
+                                list_add_tail(&urbq->urb_more, &endp->urb_more);
+                                urbq->urb = urb;
+                        }
+                }
+                return 0;
+        }
+}
+
+static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+        struct urb *urb, gfp_t mem_flags)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (irqs_disabled()) {
+                if (__GFP_WAIT & mem_flags) {
+                        printk(KERN_ERR "invalid context for function that migh"
+                                "t sleep\n");
+                        return -EINVAL;
+                }
+        }
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                return -ESHUTDOWN;
+        } else {
+                u8 usb_addr = usb_pipedevice(urb->pipe);
+                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+                struct usb_device *usb_dev = urb->dev;
+                if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+                        u8 address = u132->addr[usb_addr].address;
+                        struct u132_udev *udev = &u132->udev[address];
+                        struct u132_endp *endp = hep->hcpriv;
+                        urb->actual_length = 0;
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_int_on_old_endpoint(u132, udev,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp, address);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp,
+                                                msecs_to_jiffies(urb->interval))
+                                                ;
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else {        /*(endp == NULL) */
+                                return create_endpoint_and_queue_int(u132, udev,
+                                         hep, urb, usb_dev, usb_addr, usb_endp,
+                                        address, mem_flags);
+                        }
+                } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                        dev_err(&u132->platform_dev->dev, "the hardware does no"
+                                "t support PIPE_ISOCHRONOUS\n");
+                        return -EINVAL;
+                } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+                        u8 address = u132->addr[usb_addr].address;
+                        struct u132_udev *udev = &u132->udev[address];
+                        struct u132_endp *endp = hep->hcpriv;
+                        urb->actual_length = 0;
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_bulk_on_old_endpoint(u132, udev,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp, address);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp, 0);
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else
+                                return create_endpoint_and_queue_bulk(u132,
+                                        udev, hep, urb, usb_dev, usb_addr,
+                                        usb_endp, address, mem_flags);
+                } else {
+                        struct u132_endp *endp = hep->hcpriv;
+                        u16 urb_size = 8;
+                        u8 *b = urb->setup_packet;
+                        int i = 0;
+                        char data[30 *3 + 4];
+                        char *d = data;
+                        int m = (sizeof(data) - 1) / 3;
+                        int l = 0;
+                        data[0] = 0;
+                        while (urb_size-- > 0) {
+                                if (i > m) {
+                                } else if (i++ < m) {
+                                        int w = sprintf(d, " %02X", *b++);
+                                        d += w;
+                                        l += w;
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_control_on_old_endpoint(u132,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp, 0);
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else
+                                return create_endpoint_and_queue_control(u132,
+                                        hep, urb, usb_dev, usb_addr, usb_endp,
+                                        mem_flags);
+                }
+        }
+}
+
+static int dequeue_from_overflow_chain(struct u132 *u132,
+        struct u132_endp *endp, struct urb *urb)
+{
+        struct list_head *scan;
+        struct list_head *head = &endp->urb_more;
+        list_for_each(scan, head) {
+                struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
+                        urb_more);
+                if (urbq->urb == urb) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        list_del(scan);
+                        endp->queue_size -= 1;
+                        urb->error_count = 0;
+                        urb->hcpriv = NULL;
+                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        return 0;
+                } else
+                        continue;
+        }
+        dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
+                "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
+                "\n", urb, endp->endp_number, endp, endp->ring->number,
+                endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+                endp->usb_endp, endp->usb_addr, endp->queue_size,
+                endp->queue_next, endp->queue_last);
+        return -EINVAL;
+}
+
+static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb)
+{
+        unsigned long irqs;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        if (endp->queue_size == 0) {
+                dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
+                        "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
+                        endp->endp_number, endp, endp->ring->number,
+                        endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+                        endp->usb_endp, endp->usb_addr);
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                return -EINVAL;
+        }
+        if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
+                if (endp->active) {
+                        endp->dequeueing = 1;
+                        endp->edset_flush = 1;
+                        u132_endp_queue_work(u132, endp, 0);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        urb->hcpriv = NULL;
+                        return 0;
+                } else {
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        u132_hcd_abandon_urb(u132, endp, urb, urb->status);
+                        return 0;
+                }
+        } else {
+                u16 queue_list = 0;
+                u16 queue_size = endp->queue_size;
+                u16 queue_scan = endp->queue_next;
+                struct urb **urb_slot = NULL;
+                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                        if (urb == endp->urb_list[ENDP_QUEUE_MASK &
+                                ++queue_scan]) {
+                                urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                                        queue_scan];
+                                break;
+                        } else
+                                continue;
+                }
+                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                        *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
+                                ++queue_scan];
+                        urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                                queue_scan];
+                }
+                if (urb_slot) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        endp->queue_size -= 1;
+                        if (list_empty(&endp->urb_more)) {
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                        } else {
+                                struct list_head *next = endp->urb_more.next;
+                                struct u132_urbq *urbq = list_entry(next,
+                                        struct u132_urbq, urb_more);
+                                list_del(next);
+                                *urb_slot = urbq->urb;
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                kfree(urbq);
+                        } urb->error_count = 0;
+                        urb->hcpriv = NULL;
+                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        return 0;
+                } else if (list_empty(&endp->urb_more)) {
+                        dev_err(&u132->platform_dev->dev, "urb=%p not found in "
+                                "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
+                                "=%d size=%d next=%04X last=%04X\n", urb,
+                                endp->endp_number, endp, endp->ring->number,
+                                endp->input ? 'I' : ' ',
+                                endp->output ? 'O' : ' ', endp->usb_endp,
+                                endp->usb_addr, endp->queue_size,
+                                endp->queue_next, endp->queue_last);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        return -EINVAL;
+                } else {
+                        int retval = dequeue_from_overflow_chain(u132, endp,
+                                urb);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        return retval;
+                }
+        }
+}
+
+static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 2) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else {
+                u8 usb_addr = usb_pipedevice(urb->pipe);
+                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                if (usb_pipein(urb->pipe)) {
+                        u8 endp_number = udev->endp_number_in[usb_endp];
+                        struct u132_endp *endp = u132->endp[endp_number - 1];
+                        return u132_endp_urb_dequeue(u132, endp, urb);
+                } else {
+                        u8 endp_number = udev->endp_number_out[usb_endp];
+                        struct u132_endp *endp = u132->endp[endp_number - 1];
+                        return u132_endp_urb_dequeue(u132, endp, urb);
+                }
+        }
+}
+
+static void u132_endpoint_disable(struct usb_hcd *hcd,
+        struct usb_host_endpoint *hep)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 2) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else {
+                struct u132_endp *endp = hep->hcpriv;
+                if (endp)
+                        u132_endp_put_kref(u132, endp);
+        }
+}
+
+static int u132_get_frame(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int frame = 0;
+                dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
+                msleep(100);
+                return frame;
+        }
+}
+
+static int u132_roothub_descriptor(struct u132 *u132,
+        struct usb_hub_descriptor *desc)
+{
+        int retval;
+        u16 temp;
+        u32 rh_a = -1;
+        u32 rh_b = -1;
+        retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+        if (retval)
+                return retval;
+        desc->bDescriptorType = 0x29;
+        desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
+        desc->bHubContrCurrent = 0;
+        desc->bNbrPorts = u132->num_ports;
+        temp = 1 + (u132->num_ports / 8);
+        desc->bDescLength = 7 + 2 *temp;
+        temp = 0;
+        if (rh_a & RH_A_NPS)
+                temp |= 0x0002;
+        if (rh_a & RH_A_PSM)
+                temp |= 0x0001;
+        if (rh_a & RH_A_NOCP) {
+                temp |= 0x0010;
+        } else if (rh_a & RH_A_OCPM)
+                temp |= 0x0008;
+        desc->wHubCharacteristics = cpu_to_le16(temp);
+        retval = u132_read_pcimem(u132, roothub.b, &rh_b);
+        if (retval)
+                return retval;
+        memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
+        desc->bitmap[0] = rh_b & RH_B_DR;
+        if (u132->num_ports > 7) {
+                desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
+                desc->bitmap[2] = 0xff;
+        } else
+                desc->bitmap[1] = 0xff;
+        return 0;
+}
+
+static int u132_roothub_status(struct u132 *u132, __le32 *desc)
+{
+        u32 rh_status = -1;
+        int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
+        *desc = cpu_to_le32(rh_status);
+        return ret_status;
+}
+
+static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int port = wIndex - 1;
+                u32 rh_portstatus = -1;
+                int ret_portstatus = u132_read_pcimem(u132,
+                        roothub.portstatus[port], &rh_portstatus);
+                *desc = cpu_to_le32(rh_portstatus);
+                if (*(u16 *) (desc + 2)) {
+                        dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
+                                "ge = %08X\n", port, *desc);
+                }
+                return ret_portstatus;
+        }
+}
+
+
+/* this timer value might be vendor-specific ... */
+#define PORT_RESET_HW_MSEC 10
+#define PORT_RESET_MSEC 10
+/* wrap-aware logic morphed from <linux/jiffies.h> */
+#define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
+static int u132_roothub_portreset(struct u132 *u132, int port_index)
+{
+        int retval;
+        u32 fmnumber;
+        u16 now;
+        u16 reset_done;
+        retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+        if (retval)
+                return retval;
+        now = fmnumber;
+        reset_done = now + PORT_RESET_MSEC;
+        do {
+                u32 portstat;
+                do {
+                        retval = u132_read_pcimem(u132,
+                                roothub.portstatus[port_index], &portstat);
+                        if (retval)
+                                return retval;
+                        if (RH_PS_PRS & portstat) {
+                                continue;
+                        } else
+                                break;
+                } while (tick_before(now, reset_done));
+                if (RH_PS_PRS & portstat)
+                        return -ENODEV;
+                if (RH_PS_CCS & portstat) {
+                        if (RH_PS_PRSC & portstat) {
+                                retval = u132_write_pcimem(u132,
+                                        roothub.portstatus[port_index],
+                                        RH_PS_PRSC);
+                                if (retval)
+                                        return retval;
+                        }
+                } else
+                        break;        /* start the next reset,
+                                sleep till it's probably done */
+                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                         RH_PS_PRS);
+                if (retval)
+                        return retval;
+                msleep(PORT_RESET_HW_MSEC);
+                retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+                if (retval)
+                        return retval;
+                now = fmnumber;
+        } while (tick_before(now, reset_done));
+        return 0;
+}
+
+static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
+        u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int retval;
+                int port_index = wIndex - 1;
+                struct u132_port *port = &u132->port[port_index];
+                port->Status &= ~(1 << wValue);
+                switch (wValue) {
+                case USB_PORT_FEAT_SUSPEND:
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[port_index], RH_PS_PSS);
+                        if (retval)
+                                return retval;
+                        return 0;
+                case USB_PORT_FEAT_POWER:
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[port_index], RH_PS_PPS);
+                        if (retval)
+                                return retval;
+                        return 0;
+                case USB_PORT_FEAT_RESET:
+                        retval = u132_roothub_portreset(u132, port_index);
+                        if (retval)
+                                return retval;
+                        return 0;
+                default:
+                        return -EPIPE;
+                }
+        }
+}
+
+static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
+        u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int port_index = wIndex - 1;
+                u32 temp;
+                int retval;
+                struct u132_port *port = &u132->port[port_index];
+                port->Status &= ~(1 << wValue);
+                switch (wValue) {
+                case USB_PORT_FEAT_ENABLE:
+                        temp = RH_PS_CCS;
+                        break;
+                case USB_PORT_FEAT_C_ENABLE:
+                        temp = RH_PS_PESC;
+                        break;
+                case USB_PORT_FEAT_SUSPEND:
+                        temp = RH_PS_POCI;
+                        if ((u132->hc_control & OHCI_CTRL_HCFS)
+                                != OHCI_USB_OPER) {
+                                dev_err(&u132->platform_dev->dev, "TODO resume_"
+                                        "root_hub\n");
+                        }
+                        break;
+                case USB_PORT_FEAT_C_SUSPEND:
+                        temp = RH_PS_PSSC;
+                        break;
+                case USB_PORT_FEAT_POWER:
+                        temp = RH_PS_LSDA;
+                        break;
+                case USB_PORT_FEAT_C_CONNECTION:
+                        temp = RH_PS_CSC;
+                        break;
+                case USB_PORT_FEAT_C_OVER_CURRENT:
+                        temp = RH_PS_OCIC;
+                        break;
+                case USB_PORT_FEAT_C_RESET:
+                        temp = RH_PS_PRSC;
+                        break;
+                default:
+                        return -EPIPE;
+                }
+                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                         temp);
+                if (retval)
+                        return retval;
+                return 0;
+        }
+}
+
+
+/* the virtual root hub timer IRQ checks for hub status*/
+static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
+                        "ed %d\n", hcd, u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                        "ed\n", hcd);
+                dump_stack();
+                return -ESHUTDOWN;
+        } else {
+                int i, changed = 0, length = 1;
+                if (u132->flags & OHCI_QUIRK_AMD756) {
+                        if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
+                                dev_err(&u132->platform_dev->dev, "bogus NDP, r"
+                                        "ereads as NDP=%d\n",
+                                        u132->hc_roothub_a & RH_A_NDP);
+                                goto done;
+                        }
+                }
+                if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
+                        buf[0] = changed = 1;
+                } else
+                        buf[0] = 0;
+                if (u132->num_ports > 7) {
+                        buf[1] = 0;
+                        length++;
+                }
+                for (i = 0; i < u132->num_ports; i++) {
+                        if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
+                                RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
+                                RH_PS_PRSC)) {
+                                changed = 1;
+                                if (i < 7) {
+                                        buf[0] |= 1 << (i + 1);
+                                } else
+                                        buf[1] |= 1 << (i - 7);
+                                continue;
+                        }
+                        if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
+                                continue;
+                        }
+                        if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
+                                continue;
+                        }
+                }
+              done:return changed ? length : 0;
+        }
+}
+
+static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+        u16 wIndex, char *buf, u16 wLength)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                down(&u132->sw_lock);
+                switch (typeReq) {
+                case ClearHubFeature:
+                        switch (wValue) {
+                        case C_HUB_OVER_CURRENT:
+                        case C_HUB_LOCAL_POWER:
+                                break;
+                        default:
+                                goto stall;
+                        }
+                        break;
+                case SetHubFeature:
+                        switch (wValue) {
+                        case C_HUB_OVER_CURRENT:
+                        case C_HUB_LOCAL_POWER:
+                                break;
+                        default:
+                                goto stall;
+                        }
+                        break;
+                case ClearPortFeature:{
+                                retval = u132_roothub_clearportfeature(u132,
+                                        wValue, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetHubDescriptor:{
+                                retval = u132_roothub_descriptor(u132,
+                                        (struct usb_hub_descriptor *)buf);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetHubStatus:{
+                                retval = u132_roothub_status(u132,
+                                        (__le32 *) buf);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetPortStatus:{
+                                retval = u132_roothub_portstatus(u132,
+                                        (__le32 *) buf, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case SetPortFeature:{
+                                retval = u132_roothub_setportfeature(u132,
+                                        wValue, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                default:
+                        goto stall;
+                      error:u132_disable(u132);
+                        u132->going = 1;
+                        break;
+                      stall:retval = -EPIPE;
+                        break;
+                }
+                up(&u132->sw_lock);
+                return retval;
+        }
+}
+
+static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static void u132_hub_irq_enable(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else if (u132->going > 0)
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+}
+
+
+#ifdef CONFIG_PM
+static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_hcd_resume(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_bus_suspend(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_bus_resume(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+#else
+#define u132_hcd_suspend NULL
+#define u132_hcd_resume NULL
+#define u132_bus_suspend NULL
+#define u132_bus_resume NULL
+#endif
+static struct hc_driver u132_hc_driver = {
+        .description = hcd_name,
+        .hcd_priv_size = sizeof(struct u132),
+        .irq = NULL,
+        .flags = HCD_USB11 | HCD_MEMORY,
+        .reset = u132_hcd_reset,
+        .start = u132_hcd_start,
+        .suspend = u132_hcd_suspend,
+        .resume = u132_hcd_resume,
+        .stop = u132_hcd_stop,
+        .urb_enqueue = u132_urb_enqueue,
+        .urb_dequeue = u132_urb_dequeue,
+        .endpoint_disable = u132_endpoint_disable,
+        .get_frame_number = u132_get_frame,
+        .hub_status_data = u132_hub_status_data,
+        .hub_control = u132_hub_control,
+        .bus_suspend = u132_bus_suspend,
+        .bus_resume = u132_bus_resume,
+        .start_port_reset = u132_start_port_reset,
+        .hub_irq_enable = u132_hub_irq_enable,
+};
+
+/*
+* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
+* is held for writing, thus this module must not call usb_remove_hcd()
+* synchronously - but instead should immediately stop activity to the
+* device and ansynchronously call usb_remove_hcd()
+*/
+static int __devexit u132_remove(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        if (hcd) {
+                struct u132 *u132 = hcd_to_u132(hcd);
+                dump_stack();
+                if (u132->going++ > 1) {
+                        return -ENODEV;
+                } else {
+                        int rings = MAX_U132_RINGS;
+                        int endps = MAX_U132_ENDPS;
+                        msleep(100);
+                        down(&u132->sw_lock);
+                        u132_monitor_cancel_work(u132);
+                        while (rings-- > 0) {
+                                struct u132_ring *ring = &u132->ring[rings];
+                                u132_ring_cancel_work(u132, ring);
+                        } while (endps-- > 0) {
+                                struct u132_endp *endp = u132->endp[endps];
+                                if (endp)
+                                        u132_endp_cancel_work(u132, endp);
+                        }
+                        u132->going += 1;
+                        printk(KERN_INFO "removing device u132.%d\n",
+                                u132->sequence_num);
+                        up(&u132->sw_lock);
+                        usb_remove_hcd(hcd);
+                        u132_u132_put_kref(u132);
+                        return 0;
+                }
+        } else
+                return 0;
+}
+
+static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
+{
+        int rings = MAX_U132_RINGS;
+        int ports = MAX_U132_PORTS;
+        int addrs = MAX_U132_ADDRS;
+        int udevs = MAX_U132_UDEVS;
+        int endps = MAX_U132_ENDPS;
+        u132->board = pdev->dev.platform_data;
+        u132->platform_dev = pdev;
+        u132->power = 0;
+        u132->reset = 0;
+        init_MUTEX(&u132->sw_lock);
+        init_MUTEX(&u132->scheduler_lock);
+        while (rings-- > 0) {
+                struct u132_ring *ring = &u132->ring[rings];
+                ring->u132 = u132;
+                ring->number = rings + 1;
+                ring->length = 0;
+                ring->curr_endp = NULL;
+                INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler,
+                        (void *)ring);
+        } down(&u132->sw_lock);
+        INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132);
+        while (ports-- > 0) {
+                struct u132_port *port = &u132->port[ports];
+                port->u132 = u132;
+                port->reset = 0;
+                port->enable = 0;
+                port->power = 0;
+                port->Status = 0;
+        } while (addrs-- > 0) {
+                struct u132_addr *addr = &u132->addr[addrs];
+                addr->address = 0;
+        } while (udevs-- > 0) {
+                struct u132_udev *udev = &u132->udev[udevs];
+                int i = ARRAY_SIZE(udev->endp_number_in);
+                int o = ARRAY_SIZE(udev->endp_number_out);
+                udev->usb_device = NULL;
+                udev->udev_number = 0;
+                udev->usb_addr = 0;
+                udev->portnumber = 0;
+                while (i-- > 0) {
+                        udev->endp_number_in[i] = 0;
+                }
+                while (o-- > 0) {
+                        udev->endp_number_out[o] = 0;
+                }
+        }
+        while (endps-- > 0) {
+                u132->endp[endps] = NULL;
+        }
+        up(&u132->sw_lock);
+        return;
+}
+
+static int __devinit u132_probe(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd;
+        msleep(100);
+        if (u132_exiting > 0) {
+                return -ENODEV;
+        }                        /* refuse to confuse usbcore */
+        if (pdev->dev.dma_mask) {
+                return -EINVAL;
+        }
+        hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+        if (!hcd) {
+                printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
+                        );
+                ftdi_elan_gone_away(pdev);
+                return -ENOMEM;
+        } else {
+                int retval = 0;
+                struct u132 *u132 = hcd_to_u132(hcd);
+                hcd->rsrc_start = 0;
+                down(&u132_module_lock);
+                list_add_tail(&u132->u132_list, &u132_static_list);
+                u132->sequence_num = ++u132_instances;
+                up(&u132_module_lock);
+                u132_u132_init_kref(u132);
+                u132_initialise(u132, pdev);
+                hcd->product_desc = "ELAN U132 Host Controller";
+                retval = usb_add_hcd(hcd, 0, 0);
+                if (retval != 0) {
+                        dev_err(&u132->platform_dev->dev, "init error %d\n",
+                                retval);
+                        u132_u132_put_kref(u132);
+                        return retval;
+                } else {
+                        u132_monitor_queue_work(u132, 100);
+                        return 0;
+                }
+        }
+}
+
+
+#ifdef CONFIG_PM
+/* for this device there's no useful distinction between the controller
+* and its root hub, except that the root hub only gets direct PM calls
+* when CONFIG_USB_SUSPEND is enabled.
+*/
+static int u132_suspend(struct platform_device *pdev, pm_message_t state)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                if (state.event == PM_EVENT_FREEZE) {
+                        retval = u132_bus_suspend(hcd);
+                } else if (state.event == PM_EVENT_SUSPEND) {
+                        int ports = MAX_U132_PORTS;
+                        while (ports-- > 0) {
+                                port_power(u132, ports, 0);
+                        }
+                }
+                if (retval == 0)
+                        pdev->dev.power.power_state = state;
+                return retval;
+        }
+}
+
+static int u132_resume(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+                        int ports = MAX_U132_PORTS;
+                        while (ports-- > 0) {
+                                port_power(u132, ports, 1);
+                        }
+                        retval = 0;
+                } else {
+                        pdev->dev.power.power_state = PMSG_ON;
+                        retval = u132_bus_resume(hcd);
+                }
+                return retval;
+        }
+}
+
+#else
+#define u132_suspend NULL
+#define u132_resume NULL
+#endif
+/*
+* this driver is loaded explicitely by ftdi_u132
+*
+* the platform_driver struct is static because it is per type of module
+*/
+static struct platform_driver u132_platform_driver = {
+        .probe = u132_probe,
+        .remove = __devexit_p(u132_remove),
+        .suspend = u132_suspend,
+        .resume = u132_resume,
+        .driver = {
+                   .name = (char *)hcd_name,
+                   .owner = THIS_MODULE,
+                   },
+};
+static int __init u132_hcd_init(void)
+{
+        int retval;
+        INIT_LIST_HEAD(&u132_static_list);
+        u132_instances = 0;
+        u132_exiting = 0;
+        init_MUTEX(&u132_module_lock);
+        if (usb_disabled())
+                return -ENODEV;
+        printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
+                __DATE__);
+        workqueue = create_singlethread_workqueue("u132");
+        retval = platform_driver_register(&u132_platform_driver);
+        return retval;
+}
+
+
+module_init(u132_hcd_init);
+static void __exit u132_hcd_exit(void)
+{
+        struct u132 *u132;
+        struct u132 *temp;
+        down(&u132_module_lock);
+        u132_exiting += 1;
+        up(&u132_module_lock);
+        list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
+                platform_device_unregister(u132->platform_dev);
+        } platform_driver_unregister(&u132_platform_driver);
+        printk(KERN_INFO "u132-hcd driver deregistered\n");
+        wait_event(u132_hcd_wait, u132_instances == 0);
+        flush_workqueue(workqueue);
+        destroy_workqueue(workqueue);
+}
+
+
+module_exit(u132_hcd_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index d1372cb..e345f15 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -16,7 +16,7 @@
 
 #include "uhci-hcd.h"
 
-#define uhci_debug_operations (* (struct file_operations *) NULL)
+#define uhci_debug_operations (* (const struct file_operations *) NULL)
 static struct dentry *uhci_debugfs_root;
 
 #ifdef DEBUG
@@ -500,7 +500,7 @@
 }
 
 #undef uhci_debug_operations
-static struct file_operations uhci_debug_operations = {
+static const struct file_operations uhci_debug_operations = {
 	.owner =	THIS_MODULE,
 	.open =		uhci_debug_open,
 	.llseek =	uhci_debug_lseek,
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index c545ef9..16fb72e 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -84,6 +84,7 @@
 		unsigned long port_addr)
 {
 	int status;
+	int i;
 
 	if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
 		CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
@@ -92,9 +93,14 @@
 
 		/* The controller won't actually turn off the RD bit until
 		 * it has had a chance to send a low-speed EOP sequence,
-		 * which takes 3 bit times (= 2 microseconds).  We'll delay
-		 * slightly longer for good luck. */
-		udelay(4);
+		 * which is supposed to take 3 bit times (= 2 microseconds).
+		 * Experiments show that some controllers take longer, so
+		 * we'll poll for completion. */
+		for (i = 0; i < 10; ++i) {
+			if (!(inw(port_addr) & USBPORTSC_RD))
+				break;
+			udelay(1);
+		}
 	}
 	clear_bit(port, &uhci->resuming_ports);
 }
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 08daf40..ca6305c 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -424,7 +424,7 @@
  ***************************************************************************/
 
 static struct usb_driver mdc800_usb_driver;
-static struct file_operations mdc800_device_ops;
+static const struct file_operations mdc800_device_ops;
 static struct usb_class_driver mdc800_class = {
 	.name =		"mdc800%d",
 	.fops =		&mdc800_device_ops,
@@ -941,7 +941,7 @@
 ****************************************************************************/
 
 /* File Operations of this drivers */
-static struct file_operations mdc800_device_ops =
+static const struct file_operations mdc800_device_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		mdc800_device_read,
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index b2bafc3..5f86133 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -225,7 +225,7 @@
 }
 
 
-static inline void mts_show_command(Scsi_Cmnd *srb)
+static inline void mts_show_command(struct scsi_cmnd *srb)
 {
 	char *what = NULL;
 
@@ -309,7 +309,7 @@
 
 #else
 
-static inline void mts_show_command(Scsi_Cmnd * dummy)
+static inline void mts_show_command(struct scsi_cmnd * dummy)
 {
 }
 
@@ -338,7 +338,7 @@
 	return 0;
 }
 
-static int mts_scsi_abort (Scsi_Cmnd *srb)
+static int mts_scsi_abort(struct scsi_cmnd *srb)
 {
 	struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 
@@ -349,7 +349,7 @@
 	return FAILED;
 }
 
-static int mts_scsi_host_reset (Scsi_Cmnd *srb)
+static int mts_scsi_host_reset(struct scsi_cmnd *srb)
 {
 	struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 	int result, rc;
@@ -366,8 +366,8 @@
 	return result ? FAILED : SUCCESS;
 }
 
-static
-int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
+static int
+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);
@@ -537,7 +537,7 @@
 #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
 
 static void
-mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
+mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc)
 {
 	int pipe;
 	struct scatterlist * sg;
@@ -588,8 +588,8 @@
 }
 
 
-static
-int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
+static int
+mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 {
 	struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 	int err = 0;
diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h
index 926d4bd..d5d62a9 100644
--- a/drivers/usb/image/microtek.h
+++ b/drivers/usb/image/microtek.h
@@ -8,14 +8,14 @@
  *
  */
 
-typedef void (*mts_scsi_cmnd_callback)(Scsi_Cmnd *);
+typedef void (*mts_scsi_cmnd_callback)(struct scsi_cmnd *);
 
 
 struct mts_transfer_context
 {
 	struct mts_desc* instance;
 	mts_scsi_cmnd_callback final_callback;
-	Scsi_Cmnd *srb;
+	struct scsi_cmnd *srb;
 	
 	void* data;
 	unsigned data_length;
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 650103b..a102a58 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -205,10 +205,12 @@
 	depends on USB && INPUT
 	---help---
 	  USB Touchscreen driver for:
-	  - eGalax Touchkit USB
+	  - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
 	  - PanJit TouchSet USB
-	  - 3M MicroTouch USB
+	  - 3M MicroTouch USB (EX II series)
 	  - ITM
+	  - some other eTurboTouch
+	  - Gunze AHL61
 
 	  Have a look at <http://linux.chapter7.ch/touchkit/> for
 	  a usage description and the required user-space stuff.
@@ -218,7 +220,7 @@
 
 config USB_TOUCHSCREEN_EGALAX
 	default y
-	bool "eGalax device support" if EMBEDDED
+	bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
 	depends on USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_PANJIT
@@ -228,7 +230,7 @@
 
 config USB_TOUCHSCREEN_3M
 	default y
-	bool "3M/Microtouch device support" if EMBEDDED
+	bool "3M/Microtouch EX II series device support" if EMBEDDED
 	depends on USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_ITM
@@ -236,6 +238,16 @@
 	bool "ITM device support" if EMBEDDED
 	depends on USB_TOUCHSCREEN
 
+config USB_TOUCHSCREEN_ETURBO
+	default y
+	bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED
+	depends on USB_TOUCHSCREEN
+
+config USB_TOUCHSCREEN_GUNZE
+	default y
+	bool "Gunze AHL61 device support" if EMBEDDED
+	depends on USB_TOUCHSCREEN
+
 config USB_YEALINK
 	tristate "Yealink usb-p1k voip phone"
 	depends on USB && INPUT && EXPERIMENTAL
@@ -326,3 +338,13 @@
 
 	  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 7641145..48551be 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -3,6 +3,7 @@
 #
 
 # Multipart objects.
+wacom-objs	:= wacom_sys.o wacom_wac.o
 usbhid-objs	:= hid-core.o
 
 # Optional parts of multipart objects.
@@ -44,6 +45,7 @@
 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 18c10e1..d83603b 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -141,10 +141,7 @@
 
 	endpoint = &interface->endpoint[0].desc;
 
-	if (!(endpoint->bEndpointAddress & 0x80))
-		return -ENODEV;
-
-	if ((endpoint->bmAttributes & 3) != 3)
+	if (!usb_endpoint_is_int_in(endpoint))
 		return -ENODEV;
 
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 044faa0..0aa9cc2 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -436,10 +436,7 @@
 	iface_desc = iface->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
 		endpoint = &iface_desc->endpoint[i].desc;
-		if (!int_in_endpointAddr &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-					== USB_ENDPOINT_XFER_INT)) {
+		if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
 			/* we found an interrupt in endpoint */
 			int_in_endpointAddr = endpoint->bEndpointAddress;
 			break;
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 3719fcb..3558d7e 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -732,12 +732,8 @@
 	endpoint_in = &iface_host->endpoint[0].desc;
 	endpoint_out = &iface_host->endpoint[1].desc;
 
-	if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) {
-		err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__);
-		return -ENODEV;
-	}
-	if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
-		err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__);
+	if (!usb_endpoint_is_int_in(endpoint_in)) {
+		err("%s: Unexpected endpoint_in\n", __FUNCTION__);
 		return -ENODEV;
 	}
 	if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 3305fb6..81b1ea0 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1023,7 +1023,8 @@
 			return;
 		case -EILSEQ:		/* protocol error or unplug */
 		case -EPROTO:		/* protocol error or unplug */
-		case -ETIMEDOUT:	/* NAK */
+		case -ETIME:		/* protocol error or unplug */
+		case -ETIMEDOUT:	/* Should never happen, but... */
 			clear_bit(HID_IN_RUNNING, &hid->iofl);
 			hid_io_error(hid);
 			return;
@@ -1535,13 +1536,17 @@
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
 #define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
-#define USB_DEVICE_ID_8_8_8_IF_KIT	0x0045
 #define USB_DEVICE_ID_0_0_4_IF_KIT	0x0040
+#define USB_DEVICE_ID_0_16_16_IF_KIT	0x0044
+#define USB_DEVICE_ID_8_8_8_IF_KIT	0x0045
+#define USB_DEVICE_ID_0_8_7_IF_KIT	0x0051
 #define USB_DEVICE_ID_0_8_8_IF_KIT	0x0053
+#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL	0x0058
 
 #define USB_VENDOR_ID_WISEGROUP		0x0925
 #define USB_DEVICE_ID_1_PHIDGETSERVO_20	0x8101
 #define USB_DEVICE_ID_4_PHIDGETSERVO_20	0x8104
+#define USB_DEVICE_ID_8_8_4_IF_KIT	0x8201
 #define USB_DEVICE_ID_DUAL_USB_JOYPAD   0x8866
 
 #define USB_VENDOR_ID_WISEGROUP_LTD	0x6677
@@ -1591,6 +1596,13 @@
 
 #define USB_VENDOR_ID_YEALINK		0x6993
 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
+
+#define USB_VENDOR_ID_ALCOR		0x058f
+#define USB_DEVICE_ID_ALCOR_USBRS232	0x9720
+
+#define USB_VENDOR_ID_SUN		0x0430
+#define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -1608,6 +1620,7 @@
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
@@ -1620,9 +1633,12 @@
 	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
@@ -1690,7 +1706,11 @@
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
@@ -1701,6 +1721,7 @@
 	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
 
 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
@@ -1711,6 +1732,7 @@
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index f6b839c..a2b419d 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -722,7 +722,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations hiddev_fops = {
+static const struct file_operations hiddev_fops = {
 	.owner =	THIS_MODULE,
 	.read =		hiddev_read,
 	.write =	hiddev_write,
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 86acb5f..61966d7 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -87,7 +87,7 @@
 	case 0:
 		/* success */
 		break;
-	case -ETIMEDOUT:
+	case -ETIME:
 		/* this urb is timing out */
 		dbg("%s - urb timed out - was the device unplugged?",
 		    __FUNCTION__);
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 4723b31..a903595 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -420,8 +420,7 @@
 	for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
 		endpoint = &iface->endpoint[i].desc;
 
-		if ((endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+		if (usb_endpoint_is_int_in(endpoint)) {
 			/* we found our interrupt in endpoint */
 			return endpoint;
 		}
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index a9ccda8..5dce951 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -107,7 +107,7 @@
 	case 0:
 		/* success */
 		break;
-	case -ETIMEDOUT:
+	case -ETIME:
 		/* this urb is timing out */
 		dbg("%s - urb timed out - was the device unplugged?",
 		    __FUNCTION__);
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index b3c0d0c..f0f8db6 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -313,9 +313,7 @@
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & 0x80))
-		return -EIO;
-	if ((endpoint->bmAttributes & 3) != 3)
+	if (!usb_endpoint_is_int_in(endpoint))
 		return -EIO;
 
 	usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 0149043..30b9f82 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -201,7 +201,7 @@
 	case 0:
 		/* success */
 		break;
-	case -ETIMEDOUT:
+	case -ETIME:
 		/* this urb is timing out */
 		dbg("%s - urb timed out - was the device unplugged?",
 		    __FUNCTION__);
diff --git a/drivers/usb/input/trancevibrator.c b/drivers/usb/input/trancevibrator.c
new file mode 100644
index 0000000..33cd91d
--- /dev/null
+++ b/drivers/usb/input/trancevibrator.c
@@ -0,0 +1,159 @@
+/*
+ * PlayStation 2 Trance Vibrator driver
+ *
+ * Copyright (C) 2006 Sam Hocevar <sam@zoy.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 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.
+ */
+
+/* Standard include files */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+/* Version Information */
+#define DRIVER_VERSION "v1.1"
+#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org"
+#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver"
+
+#define TRANCEVIBRATOR_VENDOR_ID	0x0b49	/* ASCII Corporation */
+#define TRANCEVIBRATOR_PRODUCT_ID	0x064f	/* Trance Vibrator */
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) },
+	{ },
+};
+MODULE_DEVICE_TABLE (usb, id_table);
+
+/* Driver-local specific stuff */
+struct trancevibrator {
+	struct usb_device *udev;
+	unsigned int speed;
+};
+
+static ssize_t show_speed(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct trancevibrator *tv = usb_get_intfdata(intf);
+
+	return sprintf(buf, "%d\n", tv->speed);
+}
+
+static ssize_t set_speed(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct trancevibrator *tv = usb_get_intfdata(intf);
+	int temp, retval;
+
+	temp = simple_strtoul(buf, NULL, 10);
+	if (temp > 255)
+		temp = 255;
+	else if (temp < 0)
+		temp = 0;
+	tv->speed = temp;
+
+	dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed);
+
+	/* Set speed */
+	retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
+				 0x01, /* vendor request: set speed */
+				 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+				 tv->speed, /* speed value */
+				 0, NULL, 0, USB_CTRL_GET_TIMEOUT);
+	if (retval) {
+		dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
+		return retval;
+	}
+	return count;
+}
+
+static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed);
+
+static int tv_probe(struct usb_interface *interface,
+		    const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct trancevibrator *dev;
+	int retval;
+
+	dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "Out of memory\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	dev->udev = usb_get_dev(udev);
+	usb_set_intfdata(interface, dev);
+	retval = device_create_file(&interface->dev, &dev_attr_speed);
+	if (retval)
+		goto error_create_file;
+
+	return 0;
+
+error_create_file:
+	usb_put_dev(udev);
+	usb_set_intfdata(interface, NULL);
+error:
+	kfree(dev);
+	return retval;
+}
+
+static void tv_disconnect(struct usb_interface *interface)
+{
+	struct trancevibrator *dev;
+
+	dev = usb_get_intfdata (interface);
+	usb_set_intfdata(interface, NULL);
+	device_remove_file(&interface->dev, &dev_attr_speed);
+	usb_put_dev(dev->udev);
+	kfree(dev);
+}
+
+/* USB subsystem object */
+static struct usb_driver tv_driver = {
+	.name =		"trancevibrator",
+	.probe =	tv_probe,
+	.disconnect =	tv_disconnect,
+	.id_table =	id_table,
+};
+
+static int __init tv_init(void)
+{
+	int retval = usb_register(&tv_driver);
+	if (retval) {
+		err("usb_register failed. Error number %d", retval);
+		return retval;
+	}
+
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+static void __exit tv_exit(void)
+{
+	usb_deregister(&tv_driver);
+}
+
+module_init (tv_init);
+module_exit (tv_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 446935b..0fb792b 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -218,7 +218,7 @@
 
 static struct usb_device_id usb_mouse_id_table [] = {
 	{ USB_INTERFACE_INFO(3, 1, 2) },
-    { }						/* Terminating entry */
+	{ }	/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index a338bf4..4640d10 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -2,9 +2,12 @@
  * usbtouchscreen.c
  * Driver for USB Touchscreens, supporting those devices:
  *  - eGalax Touchkit
- *  - 3M/Microtouch
+ *    includes eTurboTouch CT-410/510/700
+ *  - 3M/Microtouch  EX II series
  *  - ITM
  *  - PanJit TouchSet
+ *  - eTurboTouch
+ *  - Gunze AHL61
  *
  * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -42,7 +45,7 @@
 #include <linux/usb/input.h>
 
 
-#define DRIVER_VERSION		"v0.3"
+#define DRIVER_VERSION		"v0.4"
 #define DRIVER_AUTHOR		"Daniel Ritz <daniel.ritz@gmx.ch>"
 #define DRIVER_DESC		"USB Touchscreen Driver"
 
@@ -60,6 +63,7 @@
 	int flags;
 
 	void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, 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);
 };
@@ -81,8 +85,16 @@
 	char phys[64];
 };
 
-static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
-                                 struct pt_regs *regs, unsigned char *pkt, int len);
+
+#if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO)
+#define MULTI_PACKET
+#endif
+
+#ifdef MULTI_PACKET
+static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
+                                   struct pt_regs *regs,
+                                   unsigned char *pkt, int len);
+#endif
 
 /* device types */
 enum {
@@ -91,14 +103,19 @@
 	DEVTYPE_PANJIT,
 	DEVTYPE_3M,
 	DEVTYPE_ITM,
+	DEVTYPE_ETURBO,
+	DEVTYPE_GUNZE,
 };
 
 static struct usb_device_id usbtouch_devices[] = {
 #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
 	{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
+	{USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
 	{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
 	{USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
 	{USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
+	{USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX},
+	{USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
 #endif
 
 #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
@@ -116,6 +133,14 @@
 	{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
 #endif
 
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+	{USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+	{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
+#endif
+
 	{}
 };
 
@@ -140,82 +165,23 @@
 	*touch = pkt[0] & 0x01;
 
 	return 1;
-
 }
 
-static int egalax_get_pkt_len(unsigned char *buf)
+static int egalax_get_pkt_len(unsigned char *buf, int len)
 {
 	switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
 	case EGALAX_PKT_TYPE_REPT:
 		return 5;
 
 	case EGALAX_PKT_TYPE_DIAG:
+		if (len < 2)
+			return -1;
+
 		return buf[1] + 2;
 	}
 
 	return 0;
 }
-
-static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs,
-                           unsigned char *pkt, int len)
-{
-	unsigned char *buffer;
-	int pkt_len, buf_len, pos;
-
-	/* if the buffer contains data, append */
-	if (unlikely(usbtouch->buf_len)) {
-		int tmp;
-
-		/* if only 1 byte in buffer, add another one to get length */
-		if (usbtouch->buf_len == 1)
-			usbtouch->buffer[1] = pkt[0];
-
-		pkt_len = egalax_get_pkt_len(usbtouch->buffer);
-
-		/* unknown packet: drop everything */
-		if (!pkt_len)
-			return;
-
-		/* append, process */
-		tmp = pkt_len - usbtouch->buf_len;
-		memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
-		usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
-
-		buffer = pkt + tmp;
-		buf_len = len - tmp;
-	} else {
-		buffer = pkt;
-		buf_len = len;
-	}
-
-	/* only one byte left in buffer */
-	if (unlikely(buf_len == 1)) {
-		usbtouch->buffer[0] = buffer[0];
-		usbtouch->buf_len = 1;
-		return;
-	}
-
-	/* loop over the buffer */
-	pos = 0;
-	while (pos < buf_len) {
-		/* get packet len */
-		pkt_len = egalax_get_pkt_len(buffer + pos);
-
-		/* unknown packet: drop everything */
-		if (unlikely(!pkt_len))
-			return;
-
-		/* full packet: process */
-		if (likely(pkt_len <= buf_len)) {
-			usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
-		} else {
-			/* incomplete packet: save in buffer */
-			memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
-			usbtouch->buf_len = buf_len - pos;
-		}
-		pos += pkt_len;
-	}
-}
 #endif
 
 
@@ -254,7 +220,7 @@
 
 static int mtouch_init(struct usbtouch_usb *usbtouch)
 {
-	int ret;
+	int ret, i;
 
 	ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
 	                      MTOUCHUSB_RESET,
@@ -264,15 +230,20 @@
 	    __FUNCTION__, ret);
 	if (ret < 0)
 		return ret;
+	msleep(150);
 
-	ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
-	                      MTOUCHUSB_ASYNC_REPORT,
-	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-	                      1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
-	dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
-	    __FUNCTION__, ret);
-	if (ret < 0)
-		return ret;
+	for (i = 0; i < 3; i++) {
+		ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+				      MTOUCHUSB_ASYNC_REPORT,
+				      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				      1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
+		dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
+		    __FUNCTION__, ret);
+		if (ret >= 0)
+			break;
+		if (ret != -EPIPE)
+			return ret;
+	}
 
 	return 0;
 }
@@ -296,6 +267,54 @@
 
 
 /*****************************************************************************
+ * eTurboTouch part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+	unsigned int shift;
+
+	/* packets should start with sync */
+	if (!(pkt[0] & 0x80))
+		return 0;
+
+	shift = (6 - (pkt[0] & 0x03));
+	*x = ((pkt[3] << 7) | pkt[4]) >> shift;
+	*y = ((pkt[1] << 7) | pkt[2]) >> shift;
+	*touch = (pkt[0] & 0x10) ? 1 : 0;
+
+	return 1;
+}
+
+static int eturbo_get_pkt_len(unsigned char *buf, int len)
+{
+	if (buf[0] & 0x80)
+		return 5;
+	if (buf[0] == 0x01)
+		return 3;
+	return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ * Gunze part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+	if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
+		return 0;
+
+	*x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
+	*y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
+	*touch = pkt[0] & 0x20;
+
+	return 1;
+}
+#endif
+
+/*****************************************************************************
  * the different device descriptors
  */
 static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -307,7 +326,8 @@
 		.max_yc		= 0x07ff,
 		.rept_size	= 16,
 		.flags		= USBTOUCH_FLG_BUFFER,
-		.process_pkt	= egalax_process,
+		.process_pkt	= usbtouch_process_multi,
+		.get_pkt_len	= egalax_get_pkt_len,
 		.read_data	= egalax_read_data,
 	},
 #endif
@@ -346,6 +366,31 @@
 		.read_data	= itm_read_data,
 	},
 #endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+	[DEVTYPE_ETURBO] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x07ff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x07ff,
+		.rept_size	= 8,
+		.flags		= USBTOUCH_FLG_BUFFER,
+		.process_pkt	= usbtouch_process_multi,
+		.get_pkt_len	= eturbo_get_pkt_len,
+		.read_data	= eturbo_read_data,
+	},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+	[DEVTYPE_GUNZE] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x0fff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x0fff,
+		.rept_size	= 4,
+		.read_data	= gunze_read_data,
+	},
+#endif
 };
 
 
@@ -377,6 +422,83 @@
 }
 
 
+#ifdef MULTI_PACKET
+static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
+                                   struct pt_regs *regs,
+                                   unsigned char *pkt, int len)
+{
+	unsigned char *buffer;
+	int pkt_len, pos, buf_len, tmp;
+
+	/* process buffer */
+	if (unlikely(usbtouch->buf_len)) {
+		/* try to get size */
+		pkt_len = usbtouch->type->get_pkt_len(
+				usbtouch->buffer, usbtouch->buf_len);
+
+		/* drop? */
+		if (unlikely(!pkt_len))
+			goto out_flush_buf;
+
+		/* need to append -pkt_len bytes before able to get size */
+		if (unlikely(pkt_len < 0)) {
+			int append = -pkt_len;
+			if (unlikely(append > len))
+			       append = len;
+			if (usbtouch->buf_len + append >= usbtouch->type->rept_size)
+				goto out_flush_buf;
+			memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append);
+			usbtouch->buf_len += append;
+
+			pkt_len = usbtouch->type->get_pkt_len(
+					usbtouch->buffer, usbtouch->buf_len);
+			if (pkt_len < 0)
+				return;
+		}
+
+		/* append */
+		tmp = pkt_len - usbtouch->buf_len;
+		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);
+
+		buffer = pkt + tmp;
+		buf_len = len - tmp;
+	} else {
+		buffer = pkt;
+		buf_len = len;
+	}
+
+	/* loop over the received packet, process */
+	pos = 0;
+	while (pos < buf_len) {
+		/* get packet len */
+		pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len);
+
+		/* unknown packet: drop everything */
+		if (unlikely(!pkt_len))
+			goto out_flush_buf;
+
+		/* full packet: process */
+		if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
+			usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
+		} else {
+			/* incomplete packet: save in buffer */
+			memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
+			usbtouch->buf_len = buf_len - pos;
+			return;
+		}
+		pos += pkt_len;
+	}
+
+out_flush_buf:
+	usbtouch->buf_len = 0;
+	return;
+}
+#endif
+
+
 static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
 {
 	struct usbtouch_usb *usbtouch = urb->context;
@@ -386,7 +508,7 @@
 	case 0:
 		/* success */
 		break;
-	case -ETIMEDOUT:
+	case -ETIME:
 		/* this urb is timing out */
 		dbg("%s - urb timed out - was the device unplugged?",
 		    __FUNCTION__);
@@ -452,7 +574,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct usbtouch_device_info *type;
-	int err;
+	int err = -ENOMEM;
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
@@ -526,6 +648,7 @@
 			 usbtouch->data, type->rept_size,
 			 usbtouch_irq, usbtouch, endpoint->bInterval);
 
+	usbtouch->irq->dev = usbtouch->udev;
 	usbtouch->irq->transfer_dma = usbtouch->data_dma;
 	usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -553,7 +676,7 @@
 out_free:
 	input_free_device(input_dev);
 	kfree(usbtouch);
-	return -ENOMEM;
+	return err;
 }
 
 static void usbtouch_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
deleted file mode 100644
index 369461a..0000000
--- a/drivers/usb/input/wacom.c
+++ /dev/null
@@ -1,1003 +0,0 @@
-/*
- *  USB Wacom Graphire and Wacom Intuos tablet support
- *
- *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
- *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
- *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
- *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
- *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
- *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
- *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
- *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2006 Ping Cheng		<pingc@wacom.com>
- *
- *  ChangeLog:
- *      v0.1 (vp)  - Initial release
- *      v0.2 (aba) - Support for all buttons / combinations
- *      v0.3 (vp)  - Support for Intuos added
- *	v0.4 (sm)  - Support for more Intuos models, menustrip
- *			relative mode, proximity.
- *	v0.5 (vp)  - Big cleanup, nifty features removed,
- *			they belong in userspace
- *	v1.8 (vp)  - Submit URB only when operating, moved to CVS,
- *			use input_report_key instead of report_btn and
- *			other cleanups
- *	v1.11 (vp) - Add URB ->dev setting for new kernels
- *	v1.11 (jb) - Add support for the 4D Mouse & Lens
- *	v1.12 (de) - Add support for two more inking pen IDs
- *	v1.14 (vp) - Use new USB device id probing scheme.
- *		     Fix Wacom Graphire mouse wheel
- *	v1.18 (vp) - Fix mouse wheel direction
- *		     Make mouse relative
- *      v1.20 (fl) - Report tool id for Intuos devices
- *                 - Multi tools support
- *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
- *                 - Add PL models support
- *		   - Fix Wacom Graphire mouse wheel again
- *	v1.21 (vp) - Removed protocol descriptions
- *		   - Added MISC_SERIAL for tool serial numbers
- *	      (gb) - Identify version on module load.
- *    v1.21.1 (fl) - added Graphire2 support
- *    v1.21.2 (fl) - added Intuos2 support
- *                 - added all the PL ids
- *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
- *                 - added smooth filter for Graphire from Peri Hankey
- *                 - added PenPartner support from Olaf van Es
- *                 - new tool ids from Ole Martin Bjoerndalen
- *	v1.29 (pc) - Add support for more tablets
- *		   - Fix pressure reporting
- *	v1.30 (vp) - Merge 2.4 and 2.5 drivers
- *		   - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
- *		   - Cleanups here and there
- *    v1.30.1 (pi) - Added Graphire3 support
- *	v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
- *	v1.43 (pc) - Added support for Cintiq 21UX
- *		   - Fixed a Graphire bug
- *		   - Merged wacom_intuos3_irq into wacom_intuos_irq
- *	v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
- *		   - Report Device IDs
- *	v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
- *		   - Minor data report fix
- */
-
-/*
- * 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/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-#include <asm/unaligned.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.45"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-#define USB_VENDOR_ID_WACOM	0x056a
-#define STYLUS_DEVICE_ID	0x02
-#define CURSOR_DEVICE_ID	0x06
-#define ERASER_DEVICE_ID	0x0A
-
-enum {
-	PENPARTNER = 0,
-	GRAPHIRE,
-	WACOM_G4,
-	PL,
-	INTUOS,
-	INTUOS3,
-	INTUOS312,
-	INTUOS319,
-	CINTIQ,
-	MAX_TYPE
-};
-
-struct wacom_features {
-	char *name;
-	int pktlen;
-	int x_max;
-	int y_max;
-	int pressure_max;
-	int distance_max;
-	int type;
-	usb_complete_t irq;
-};
-
-struct wacom {
-	signed char *data;
-	dma_addr_t data_dma;
-	struct input_dev *dev;
-	struct usb_device *usbdev;
-	struct urb *irq;
-	struct wacom_features *features;
-	int tool[2];
-	int id[2];
-	__u32 serial[2];
-	char phys[32];
-};
-
-#define USB_REQ_GET_REPORT	0x01
-#define USB_REQ_SET_REPORT	0x09
-
-static int usb_get_report(struct usb_interface *intf, unsigned char type,
-				unsigned char id, void *buf, int size)
-{
-	return usb_control_msg(interface_to_usbdev(intf),
-		usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
-		USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		(type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-		buf, size, 100);
-}
-
-static int usb_set_report(struct usb_interface *intf, unsigned char type,
-				unsigned char id, void *buf, int size)
-{
-	return usb_control_msg(interface_to_usbdev(intf),
-		usb_sndctrlpipe(interface_to_usbdev(intf), 0),
-                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-		buf, size, 1000);
-}
-
-static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = wacom->dev;
-	int prox, pressure, id;
-	int retval;
-
-	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;
-	}
-
-	if (data[0] != 2) {
-		dbg("wacom_pl_irq: received unknown report #%d", data[0]);
-		goto exit;
-	}
-
-	prox = data[1] & 0x40;
-
-	input_regs(dev, regs);
-
-	id = ERASER_DEVICE_ID;
-	if (prox) {
-
-		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
-		if (wacom->features->pressure_max > 255)
-			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
-		pressure += (wacom->features->pressure_max + 1) / 2;
-
-		/*
-		 * if going from out of proximity into proximity select between the eraser
-		 * and the pen based on the state of the stylus2 button, choose eraser if
-		 * pressed else choose pen. if not a proximity change from out to in, send
-		 * an out of proximity for previous tool then a in for new tool.
-		 */
-		if (!wacom->tool[0]) {
-			/* Eraser bit set for DTF */
-			if (data[1] & 0x10)
-				wacom->tool[1] = BTN_TOOL_RUBBER;
-			else
-				/* Going into proximity select tool */
-				wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-		} else {
-			/* was entered with stylus2 pressed */
-			if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
-				/* report out proximity for previous tool */
-				input_report_key(dev, wacom->tool[1], 0);
-				input_sync(dev);
-				wacom->tool[1] = BTN_TOOL_PEN;
-				goto exit;
-			}
-		}
-		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-			/* Unknown tool selected default to pen tool */
-			wacom->tool[1] = BTN_TOOL_PEN;
-			id = STYLUS_DEVICE_ID;
-		}
-		input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
-		input_report_abs(dev, ABS_MISC, id); /* report tool id */
-		input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
-		input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
-		input_report_abs(dev, ABS_PRESSURE, pressure);
-
-		input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
-		input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
-		/* Only allow the stylus2 button to be reported for the pen tool. */
-		input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
-	} else {
-		/* report proximity-out of a (valid) tool */
-		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-			/* Unknown tool selected default to pen tool */
-			wacom->tool[1] = BTN_TOOL_PEN;
-		}
-		input_report_key(dev, wacom->tool[1], prox);
-	}
-
-	wacom->tool[0] = prox; /* Save proximity state */
-	input_sync(dev);
-
- exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
-	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
-}
-
-static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = wacom->dev;
-	int retval, id;
-
-	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;
-	}
-
-	if (data[0] != 2) {
-		printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
-		goto exit;
-	}
-
-	input_regs(dev, regs);
-	if (data[1] & 0x04) {
-		input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
-		input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
-		id = ERASER_DEVICE_ID;
-	} else {
-		input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
-		input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-		id = STYLUS_DEVICE_ID;
-	}
-	input_report_abs(dev, ABS_MISC, id); /* report tool id */
-	input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
-	input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
-	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
-	input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-	input_report_key(dev, BTN_STYLUS2, data[1] & 0x10);
-
-	input_sync(dev);
-
- exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
-	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
-}
-
-static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = wacom->dev;
-	int retval;
-
-	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;
-	}
-
-	if (data[0] != 2) {
-		printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
-		goto exit;
-	}
-
-	input_regs(dev, regs);
-	input_report_key(dev, BTN_TOOL_PEN, 1);
-	input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
-	input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
-	input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
-	input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
-	input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
-	input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
-	input_sync(dev);
-
- exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
-	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
-}
-
-static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = wacom->dev;
-	int x, y, id, rw;
-	int retval;
-
-	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;
-	}
-
-	if (data[0] == 99) return; /* for Volito tablets */
-
-	if (data[0] != 2) {
-		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
-		goto exit;
-	}
-
-	input_regs(dev, regs);
-
-	id = STYLUS_DEVICE_ID;
-	if (data[1] & 0x10) { /* in prox */
-
-		switch ((data[1] >> 5) & 3) {
-
-			case 0:	/* Pen */
-				wacom->tool[0] = BTN_TOOL_PEN;
-				break;
-
-			case 1: /* Rubber */
-				wacom->tool[0] = BTN_TOOL_RUBBER;
-				id = ERASER_DEVICE_ID;
-				break;
-
-			case 2: /* Mouse with wheel */
-				input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
-				if (wacom->features->type == WACOM_G4) {
-					rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
-					input_report_rel(dev, REL_WHEEL, -rw);
-				} else
-					input_report_rel(dev, REL_WHEEL, -(signed char) data[6]);
-				/* fall through */
-
-			case 3: /* Mouse without wheel */
-				wacom->tool[0] = BTN_TOOL_MOUSE;
-				id = CURSOR_DEVICE_ID;
-				input_report_key(dev, BTN_LEFT, data[1] & 0x01);
-				input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
-				if (wacom->features->type == WACOM_G4)
-					input_report_abs(dev, ABS_DISTANCE, data[6]);
-				else
-					input_report_abs(dev, ABS_DISTANCE, data[7]);
-				break;
-		}
-	}
-
-	if (data[1] & 0x90) {
-		x = le16_to_cpu(*(__le16 *) &data[2]);
-		y = le16_to_cpu(*(__le16 *) &data[4]);
-		input_report_abs(dev, ABS_X, x);
-		input_report_abs(dev, ABS_Y, y);
-		if (wacom->tool[0] != BTN_TOOL_MOUSE) {
-			input_report_abs(dev, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
-			input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-			input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-			input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
-		}
-	}
-
-	if (data[1] & 0x10)
-		input_report_abs(dev, ABS_MISC, id); /* report tool id */
-	else
-		input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
-	input_report_key(dev, wacom->tool[0], data[1] & 0x10);
-	input_sync(dev);
-
-	/* send pad data */
-	if (wacom->features->type == WACOM_G4) {
-		if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) {
-			wacom->id[1] = 1;
-			wacom->serial[1] = (data[7] & 0xf8);
-			input_report_key(dev, BTN_0, (data[7] & 0x40));
-			input_report_key(dev, BTN_4, (data[7] & 0x80));
-			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
-			input_report_rel(dev, REL_WHEEL, rw);
-			input_report_key(dev, BTN_TOOL_FINGER, 0xf0);
-			input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
-		} else if (wacom->id[1]) {
-			wacom->id[1] = 0;
-			input_report_key(dev, BTN_TOOL_FINGER, 0);
-			input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
-		}
-		input_sync(dev);
-	}
- exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
-	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
-}
-
-static int wacom_intuos_inout(struct urb *urb)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = wacom->dev;
-	int idx;
-
-	/* tool number */
-	idx = data[1] & 0x01;
-
-	/* Enter report */
-	if ((data[1] & 0xfc) == 0xc0) {
-		/* serial number of the tool */
-		wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
-			(data[4] << 20) + (data[5] << 12) +
-			(data[6] << 4) + (data[7] >> 4);
-
-		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
-		switch (wacom->id[idx]) {
-			case 0x812: /* Inking pen */
-			case 0x801: /* Intuos3 Inking pen */
-			case 0x012:
-				wacom->tool[idx] = BTN_TOOL_PENCIL;
-				break;
-			case 0x822: /* Pen */
-			case 0x842:
-			case 0x852:
-			case 0x823: /* Intuos3 Grip Pen */
-			case 0x813: /* Intuos3 Classic Pen */
-			case 0x885: /* Intuos3 Marker Pen */
-			case 0x022:
-				wacom->tool[idx] = BTN_TOOL_PEN;
-				break;
-			case 0x832: /* Stroke pen */
-			case 0x032:
-				wacom->tool[idx] = BTN_TOOL_BRUSH;
-				break;
-			case 0x007: /* Mouse 4D and 2D */
-		        case 0x09c:
-			case 0x094:
-			case 0x017: /* Intuos3 2D Mouse */
-				wacom->tool[idx] = BTN_TOOL_MOUSE;
-				break;
-			case 0x096: /* Lens cursor */
-			case 0x097: /* Intuos3 Lens cursor */
-				wacom->tool[idx] = BTN_TOOL_LENS;
-				break;
-			case 0x82a: /* Eraser */
-			case 0x85a:
-		        case 0x91a:
-			case 0xd1a:
-			case 0x0fa:
-			case 0x82b: /* Intuos3 Grip Pen Eraser */
-			case 0x81b: /* Intuos3 Classic Pen Eraser */
-			case 0x91b: /* Intuos3 Airbrush Eraser */
-				wacom->tool[idx] = BTN_TOOL_RUBBER;
-				break;
-			case 0xd12:
-			case 0x912:
-			case 0x112:
-			case 0x913: /* Intuos3 Airbrush */
-				wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
-				break;
-			default: /* Unknown tool */
-				wacom->tool[idx] = BTN_TOOL_PEN;
-		}
-		if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
-				((wacom->features->type == INTUOS312)
-					|| (wacom->features->type == INTUOS319)))) {
-			input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
-			input_report_key(dev, wacom->tool[idx], 1);
-			input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-			input_sync(dev);
-		}
-		return 1;
-	}
-
-	/* Exit report */
-	if ((data[1] & 0xfe) == 0x80) {
-		input_report_key(dev, wacom->tool[idx], 0);
-		input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
-		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-		input_sync(dev);
-		return 1;
-	}
-
-	if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312)
-			|| (wacom->features->type == INTUOS319)))
-		return 1;
-	else
-		return 0;
-}
-
-static void wacom_intuos_general(struct urb *urb)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = wacom->dev;
-	unsigned int t;
-
-	/* general pen packet */
-	if ((data[1] & 0xb8) == 0xa0) {
-		t = (data[6] << 2) | ((data[7] >> 6) & 3);
-		input_report_abs(dev, ABS_PRESSURE, t);
-		input_report_abs(dev, ABS_TILT_X,
-				((data[7] << 1) & 0x7e) | (data[8] >> 7));
-		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-		input_report_key(dev, BTN_STYLUS, data[1] & 2);
-		input_report_key(dev, BTN_STYLUS2, data[1] & 4);
-		input_report_key(dev, BTN_TOUCH, t > 10);
-	}
-
-	/* airbrush second packet */
-	if ((data[1] & 0xbc) == 0xb4) {
-		input_report_abs(dev, ABS_WHEEL,
-				(data[6] << 2) | ((data[7] >> 6) & 3));
-		input_report_abs(dev, ABS_TILT_X,
-				((data[7] << 1) & 0x7e) | (data[8] >> 7));
-		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-	}
-	return;
-}
-
-static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = wacom->dev;
-	unsigned int t;
-	int idx;
-	int retval;
-
-	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;
-	}
-
-	if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
-		dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
-		goto exit;
-	}
-
-	input_regs(dev, regs);
-
-	/* tool number */
-	idx = data[1] & 0x01;
-
-	/* pad packets. Works as a second tool and is always in prox */
-	if (data[0] == 12) {
-		/* initiate the pad as a device */
-		if (wacom->tool[1] != BTN_TOOL_FINGER)
-			wacom->tool[1] = BTN_TOOL_FINGER;
-
-		input_report_key(dev, BTN_0, (data[5] & 0x01));
-		input_report_key(dev, BTN_1, (data[5] & 0x02));
-		input_report_key(dev, BTN_2, (data[5] & 0x04));
-		input_report_key(dev, BTN_3, (data[5] & 0x08));
-		input_report_key(dev, BTN_4, (data[6] & 0x01));
-		input_report_key(dev, BTN_5, (data[6] & 0x02));
-		input_report_key(dev, BTN_6, (data[6] & 0x04));
-		input_report_key(dev, BTN_7, (data[6] & 0x08));
-		input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
-		input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
-
-		if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
-			input_report_key(dev, wacom->tool[1], 1);
-		else
-			input_report_key(dev, wacom->tool[1], 0);
-		input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
-		input_sync(dev);
-		goto exit;
-	}
-
-	/* process in/out prox events */
-	if (wacom_intuos_inout(urb))
-		goto exit;
-
-	/* Cintiq doesn't send data when RDY bit isn't set */
-	if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
-		goto exit;
-
-	if (wacom->features->type >= INTUOS3) {
-		input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
-		input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
-		input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
-	} else {
-		input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
-		input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
-		input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
-	}
-
-	/* process general packets */
-	wacom_intuos_general(urb);
-
-	/* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
-	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
-
-		if (data[1] & 0x02) {
-			/* Rotation packet */
-			if (wacom->features->type >= INTUOS3) {
-				/* I3 marker pen rotation reported as wheel
-				 * due to valuator limitation
-				 */
-				t = (data[6] << 3) | ((data[7] >> 5) & 7);
-				t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
-					((t-1) / 2 + 450)) : (450 - t / 2) ;
-				input_report_abs(dev, ABS_WHEEL, t);
-			} else {
-				/* 4D mouse rotation packet */
-				t = (data[6] << 3) | ((data[7] >> 5) & 7);
-				input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
-					((t - 1) / 2) : -t / 2);
-			}
-
-		} else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
-			/* 4D mouse packet */
-			input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
-			input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
-			input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
-
-			input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
-			input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
-			t = (data[6] << 2) | ((data[7] >> 6) & 3);
-			input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
-
-		} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
-			/* 2D mouse packet */
-			input_report_key(dev, BTN_LEFT,   data[8] & 0x04);
-			input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
-			input_report_key(dev, BTN_RIGHT,  data[8] & 0x10);
-			input_report_rel(dev, REL_WHEEL, (data[8] & 0x01)
-						 - ((data[8] & 0x02) >> 1));
-
-			/* I3 2D mouse side buttons */
-			if (wacom->features->type == INTUOS3) {
-				input_report_key(dev, BTN_SIDE,   data[8] & 0x40);
-				input_report_key(dev, BTN_EXTRA,  data[8] & 0x20);
-			}
-
-		} else if (wacom->features->type < INTUOS3) {
-			/* Lens cursor packets */
-			input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
-			input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
-			input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
-			input_report_key(dev, BTN_SIDE,   data[8] & 0x10);
-			input_report_key(dev, BTN_EXTRA,  data[8] & 0x08);
-		}
-	}
-
-	input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
-	input_report_key(dev, wacom->tool[idx], 1);
-	input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-	input_sync(dev);
-
-exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
-	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
-		    __FUNCTION__, retval);
-}
-
-static struct wacom_features wacom_features[] = {
-	{ "Wacom Penpartner",    7,   5040,  3780,  255, 32, PENPARTNER, wacom_penpartner_irq },
-        { "Wacom Graphire",      8,  10206,  7422,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Graphire3",     8,  10208,  7424,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 32, WACOM_G4,	 wacom_graphire_irq },
-	{ "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 32, WACOM_G4,	 wacom_graphire_irq },
-	{ "Wacom Volito",        8,   5104,  3712,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom PenStation2",   8,   3250,  2320,  255, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom PenPartner2",   8,   3250,  2320,  255, 32, GRAPHIRE,   wacom_graphire_irq },
-	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom PL400",         8,   5408,  4056,  255, 32, PL,         wacom_pl_irq },
-	{ "Wacom PL500",         8,   6144,  4608,  255, 32, PL,         wacom_pl_irq },
-	{ "Wacom PL600",         8,   6126,  4604,  255, 32, PL,         wacom_pl_irq },
-	{ "Wacom PL600SX",       8,   6260,  5016,  255, 32, PL,         wacom_pl_irq },
-	{ "Wacom PL550",         8,   6144,  4608,  511, 32, PL,         wacom_pl_irq },
-	{ "Wacom PL800",         8,   7220,  5780,  511, 32, PL,         wacom_pl_irq },
-	{ "Wacom PL700",         8,   6758,  5406,  511, 32, PL,	 wacom_pl_irq },
-	{ "Wacom PL510",         8,   6282,  4762,  511, 32, PL,	 wacom_pl_irq },
-	{ "Wacom DTU710",        8,  34080, 27660,  511, 32, PL,	 wacom_pl_irq },
-	{ "Wacom DTF521",        8,   6282,  4762,  511, 32, PL,         wacom_pl_irq },
-	{ "Wacom DTF720",        8,   6858,  5506,  511, 32, PL,	 wacom_pl_irq },
-	{ "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, PL,         wacom_ptu_irq },
-	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, INTUOS3,    wacom_intuos_irq },
-	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, INTUOS3,    wacom_intuos_irq },
-	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, INTUOS3,    wacom_intuos_irq },
-	{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312,  wacom_intuos_irq },
-	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319,  wacom_intuos_irq },
-	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 15, INTUOS3,    wacom_intuos_irq },
-	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 15, CINTIQ,     wacom_intuos_irq },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-	{ }
-};
-
-static struct usb_device_id wacom_ids[] = {
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
-	{ 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, 0x3F) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, wacom_ids);
-
-static int wacom_open(struct input_dev *dev)
-{
-	struct wacom *wacom = dev->private;
-
-	wacom->irq->dev = wacom->usbdev;
-	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void wacom_close(struct input_dev *dev)
-{
-	struct wacom *wacom = dev->private;
-
-	usb_kill_urb(wacom->irq);
-}
-
-static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_endpoint_descriptor *endpoint;
-	struct wacom *wacom;
-	struct input_dev *input_dev;
-	char rep_data[2], limit = 0;
-
-	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!wacom || !input_dev)
-		goto fail1;
-
-	wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
-	if (!wacom->data)
-		goto fail1;
-
-	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!wacom->irq)
-		goto fail2;
-
-	wacom->usbdev = dev;
-	wacom->dev = input_dev;
-	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
-	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
-
-	wacom->features = wacom_features + (id - wacom_ids);
-	if (wacom->features->pktlen > 10)
-		BUG();
-
-	input_dev->name = wacom->features->name;
-	usb_to_input_id(dev, &input_dev->id);
-
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = wacom;
-	input_dev->open = wacom_open;
-	input_dev->close = wacom_close;
-
-	input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
-	input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
-	input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
-
-	switch (wacom->features->type) {
-		case WACOM_G4:
-			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);
-			/* fall through */
-
-		case GRAPHIRE:
-			input_dev->evbit[0] |= BIT(EV_REL);
-			input_dev->relbit[0] |= BIT(REL_WHEEL);
-			input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
-			input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
-			break;
-
-		case INTUOS3:
-		case INTUOS312:
-		case INTUOS319:
-		case CINTIQ:
-			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_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
-			input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
-			/* fall through */
-
-		case INTUOS:
-			input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
-			input_dev->mscbit[0] |= BIT(MSC_SERIAL);
-			input_dev->relbit[0] |= BIT(REL_WHEEL);
-			input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE)	| BIT(BTN_TOOL_BRUSH)
-							  | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
-			input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
-			input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
-			input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
-			input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
-			input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
-			input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
-			break;
-
-		case PL:
-			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
-			break;
-	}
-
-	endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
-	if (wacom->features->pktlen > 10)
-		BUG();
-
-	usb_fill_int_urb(wacom->irq, dev,
-			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-			 wacom->data, wacom->features->pktlen,
-			 wacom->features->irq, wacom, endpoint->bInterval);
-	wacom->irq->transfer_dma = wacom->data_dma;
-	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	input_register_device(wacom->dev);
-
-	/* Ask the tablet to report tablet data. Repeat until it succeeds */
-	do {
-		rep_data[0] = 2;
-		rep_data[1] = 2;
-		usb_set_report(intf, 3, 2, rep_data, 2);
-		usb_get_report(intf, 3, 2, rep_data, 2);
-	} while (rep_data[1] != 2 && limit++ < 5);
-
-	usb_set_intfdata(intf, wacom);
-	return 0;
-
-fail2:	usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
-fail1:	input_free_device(input_dev);
-	kfree(wacom);
-	return -ENOMEM;
-}
-
-static void wacom_disconnect(struct usb_interface *intf)
-{
-	struct wacom *wacom = usb_get_intfdata (intf);
-
-	usb_set_intfdata(intf, NULL);
-	if (wacom) {
-		usb_kill_urb(wacom->irq);
-		input_unregister_device(wacom->dev);
-		usb_free_urb(wacom->irq);
-		usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma);
-		kfree(wacom);
-	}
-}
-
-static struct usb_driver wacom_driver = {
-	.name =		"wacom",
-	.probe =	wacom_probe,
-	.disconnect =	wacom_disconnect,
-	.id_table =	wacom_ids,
-};
-
-static int __init wacom_init(void)
-{
-	int result = usb_register(&wacom_driver);
-	if (result == 0)
-		info(DRIVER_VERSION ":" DRIVER_DESC);
-	return result;
-}
-
-static void __exit wacom_exit(void)
-{
-	usb_deregister(&wacom_driver);
-}
-
-module_init(wacom_init);
-module_exit(wacom_exit);
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h
new file mode 100644
index 0000000..832737b
--- /dev/null
+++ b/drivers/usb/input/wacom.h
@@ -0,0 +1,132 @@
+/*
+ * drivers/usb/input/wacom.h
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support
+ *
+ *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
+ *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
+ *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
+ *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
+ *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
+ *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
+ *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
+ *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
+ *  Copyright (c) 2002-2006 Ping Cheng		<pingc@wacom.com>
+ *
+ *  ChangeLog:
+ *      v0.1 (vp)  - Initial release
+ *      v0.2 (aba) - Support for all buttons / combinations
+ *      v0.3 (vp)  - Support for Intuos added
+ *	v0.4 (sm)  - Support for more Intuos models, menustrip
+ *			relative mode, proximity.
+ *	v0.5 (vp)  - Big cleanup, nifty features removed,
+ *			they belong in userspace
+ *	v1.8 (vp)  - Submit URB only when operating, moved to CVS,
+ *			use input_report_key instead of report_btn and
+ *			other cleanups
+ *	v1.11 (vp) - Add URB ->dev setting for new kernels
+ *	v1.11 (jb) - Add support for the 4D Mouse & Lens
+ *	v1.12 (de) - Add support for two more inking pen IDs
+ *	v1.14 (vp) - Use new USB device id probing scheme.
+ *		     Fix Wacom Graphire mouse wheel
+ *	v1.18 (vp) - Fix mouse wheel direction
+ *		     Make mouse relative
+ *      v1.20 (fl) - Report tool id for Intuos devices
+ *                 - Multi tools support
+ *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
+ *                 - Add PL models support
+ *		   - Fix Wacom Graphire mouse wheel again
+ *	v1.21 (vp) - Removed protocol descriptions
+ *		   - Added MISC_SERIAL for tool serial numbers
+ *	      (gb) - Identify version on module load.
+ *    v1.21.1 (fl) - added Graphire2 support
+ *    v1.21.2 (fl) - added Intuos2 support
+ *                 - added all the PL ids
+ *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
+ *                 - added smooth filter for Graphire from Peri Hankey
+ *                 - added PenPartner support from Olaf van Es
+ *                 - new tool ids from Ole Martin Bjoerndalen
+ *	v1.29 (pc) - Add support for more tablets
+ *		   - Fix pressure reporting
+ *	v1.30 (vp) - Merge 2.4 and 2.5 drivers
+ *		   - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
+ *		   - Cleanups here and there
+ *    v1.30.1 (pi) - Added Graphire3 support
+ *	v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
+ *	v1.43 (pc) - Added support for Cintiq 21UX
+ *		   - Fixed a Graphire bug
+ *		   - Merged wacom_intuos3_irq into wacom_intuos_irq
+ *	v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
+ *		   - Report Device IDs
+ *      v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
+ *                 - Minor data report fix
+ *      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
+ */
+
+/*
+ * 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 WACOM_H
+#define WACOM_H
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+#include <asm/unaligned.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.46"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+#define USB_VENDOR_ID_WACOM	0x056a
+
+struct wacom {
+	dma_addr_t data_dma;
+	struct input_dev *dev;
+	struct usb_device *usbdev;
+	struct urb *irq;
+	struct wacom_wac * wacom_wac;
+	char phys[32];
+};
+
+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_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_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);
+extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern __u16 wacom_le16_to_cpu(unsigned char *data);
+extern __u16 wacom_be16_to_cpu(unsigned char *data);
+extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
+extern const struct usb_device_id * get_device_table(void);
+
+#endif
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
new file mode 100644
index 0000000..7c3b52b
--- /dev/null
+++ b/drivers/usb/input/wacom_sys.c
@@ -0,0 +1,315 @@
+/*
+ * drivers/usb/input/wacom_sys.c
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support - system specific code
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "wacom.h"
+#include "wacom_wac.h"
+
+#define USB_REQ_GET_REPORT	0x01
+#define USB_REQ_SET_REPORT	0x09
+
+static int usb_get_report(struct usb_interface *intf, unsigned char type,
+				unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(interface_to_usbdev(intf),
+		usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
+		USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		(type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+		buf, size, 100);
+}
+
+static int usb_set_report(struct usb_interface *intf, unsigned char type,
+				unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(interface_to_usbdev(intf),
+		usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+		buf, size, 1000);
+}
+
+static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
+{
+	return wcombo->wacom->dev;
+}
+
+void wacom_sys_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct wacom *wacom = urb->context;
+	struct wacom_combo wcombo;
+	int retval;
+
+	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;
+	}
+
+	wcombo.wacom = wacom;
+	wcombo.urb = urb;
+	wcombo.regs = regs;
+
+	if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo))
+		input_sync(get_input_dev(&wcombo));
+
+ exit:
+	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	if (retval)
+		err ("%s - usb_submit_urb failed with result %d",
+		     __FUNCTION__, retval);
+}
+
+void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
+{
+	input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data);
+	return;
+}
+
+void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data)
+{
+	input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data);
+	return;
+}
+
+void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data)
+{
+	input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data);
+	return;
+}
+
+void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value)
+{
+	input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value);
+	return;
+}
+
+__u16 wacom_be16_to_cpu(unsigned char *data)
+{
+	__u16 value;
+	value = be16_to_cpu(*(__be16 *) data);
+	return value;
+}
+
+__u16 wacom_le16_to_cpu(unsigned char *data)
+{
+	__u16 value;
+	value = be16_to_cpu(*(__be16 *) 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));
+	return;
+}
+
+static int wacom_open(struct input_dev *dev)
+{
+	struct wacom *wacom = dev->private;
+
+	wacom->irq->dev = wacom->usbdev;
+	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+		return -EIO;
+
+	return 0;
+}
+
+static void wacom_close(struct input_dev *dev)
+{
+	struct wacom *wacom = dev->private;
+
+	usb_kill_urb(wacom->irq);
+}
+
+void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	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);
+}
+
+void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->evbit[0] |= BIT(EV_REL);
+	input_dev->relbit[0] |= BIT(REL_WHEEL);
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+	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)
+{
+	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_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+	input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
+}
+
+void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
+	input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+	input_dev->relbit[0] |= BIT(REL_WHEEL);
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE)	| BIT(BTN_TOOL_BRUSH)
+		| BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
+	input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
+	input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
+	input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+	input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+	input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
+}
+
+void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
+}
+
+void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER);
+}
+
+static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_endpoint_descriptor *endpoint;
+	struct wacom *wacom;
+	struct wacom_wac *wacom_wac;
+	struct input_dev *input_dev;
+	char rep_data[2], limit = 0;
+
+	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+	wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!wacom || !input_dev || !wacom_wac)
+		goto fail1;
+
+	wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
+	if (!wacom_wac->data)
+		goto fail1;
+
+	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!wacom->irq)
+		goto fail2;
+
+	wacom->usbdev = dev;
+	wacom->dev = input_dev;
+	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
+
+	wacom_wac->features = get_wacom_feature(id);
+	if (wacom_wac->features->pktlen > 10)
+		BUG();
+
+	input_dev->name = wacom_wac->features->name;
+	wacom->wacom_wac = wacom_wac;
+	usb_to_input_id(dev, &input_dev->id);
+
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = wacom;
+	input_dev->open = wacom_open;
+	input_dev->close = wacom_close;
+
+	input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+	input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
+	input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
+
+	wacom_init_input_dev(input_dev, wacom_wac);
+
+	endpoint = &intf->cur_altsetting->endpoint[0].desc;
+
+	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->irq->transfer_dma = wacom->data_dma;
+	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	input_register_device(wacom->dev);
+
+	/* Ask the tablet to report tablet data. Repeat until it succeeds */
+	do {
+		rep_data[0] = 2;
+		rep_data[1] = 2;
+		usb_set_report(intf, 3, 2, rep_data, 2);
+		usb_get_report(intf, 3, 2, rep_data, 2);
+	} while (rep_data[1] != 2 && limit++ < 5);
+
+	usb_set_intfdata(intf, wacom);
+	return 0;
+
+fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+fail1:	input_free_device(input_dev);
+	kfree(wacom);
+	kfree(wacom_wac);
+	return -ENOMEM;
+}
+
+static void wacom_disconnect(struct usb_interface *intf)
+{
+	struct wacom *wacom = usb_get_intfdata (intf);
+
+	usb_set_intfdata(intf, NULL);
+	if (wacom) {
+		usb_kill_urb(wacom->irq);
+		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);
+	}
+}
+
+static struct usb_driver wacom_driver = {
+	.name =		"wacom",
+	.probe =	wacom_probe,
+	.disconnect =	wacom_disconnect,
+};
+
+static int __init wacom_init(void)
+{
+	int result;
+	wacom_driver.id_table = get_device_table();
+	result = usb_register(&wacom_driver);
+	if (result == 0)
+		info(DRIVER_VERSION ":" DRIVER_DESC);
+	return result;
+}
+
+static void __exit wacom_exit(void)
+{
+	usb_deregister(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
new file mode 100644
index 0000000..85d458c
--- /dev/null
+++ b/drivers/usb/input/wacom_wac.c
@@ -0,0 +1,646 @@
+/*
+ * drivers/usb/input/wacom_wac.c
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include "wacom.h"
+#include "wacom_wac.h"
+
+static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo)
+{
+	unsigned char *data = wacom->data;
+
+	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;
+				wacom_report_key(wcombo, wacom->tool[0], 1);
+				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
+				wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+				wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+				wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
+				wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127));
+				wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
+			} else {
+				wacom_report_key(wcombo, wacom->tool[0], 0);
+				wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */
+				wacom_report_abs(wcombo, ABS_PRESSURE, -1);
+				wacom_report_key(wcombo, BTN_TOUCH, 0);
+			}
+			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]));
+			wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+			wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
+			wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
+			wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
+			break;
+		default:
+			printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
+			return 0;
+        }
+	return 1;
+}
+
+static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
+{
+	unsigned char *data = wacom->data;
+	int prox, id, pressure;
+
+	if (data[0] != 2) {
+		dbg("wacom_pl_irq: received unknown report #%d", data[0]);
+		return 0;
+	}
+
+	prox = data[1] & 0x40;
+
+	wacom_input_regs(wcombo);
+
+	id = ERASER_DEVICE_ID;
+	if (prox) {
+
+		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
+		if (wacom->features->pressure_max > 255)
+			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+		pressure += (wacom->features->pressure_max + 1) / 2;
+
+		/*
+		 * if going from out of proximity into proximity select between the eraser
+		 * and the pen based on the state of the stylus2 button, choose eraser if
+		 * pressed else choose pen. if not a proximity change from out to in, send
+		 * an out of proximity for previous tool then a in for new tool.
+		 */
+		if (!wacom->tool[0]) {
+			/* Eraser bit set for DTF */
+			if (data[1] & 0x10)
+				wacom->tool[1] = BTN_TOOL_RUBBER;
+			else
+				/* Going into proximity select tool */
+				wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		} else {
+			/* was entered with stylus2 pressed */
+			if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
+				/* report out proximity for previous tool */
+				wacom_report_key(wcombo, wacom->tool[1], 0);
+				wacom_input_sync(wcombo);
+				wacom->tool[1] = BTN_TOOL_PEN;
+				return 0;
+			}
+		}
+		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+			/* Unknown tool selected default to pen tool */
+			wacom->tool[1] = BTN_TOOL_PEN;
+			id = STYLUS_DEVICE_ID;
+		}
+		wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */
+		wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+		wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
+		wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
+		wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
+
+		wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08);
+		wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10);
+		/* Only allow the stylus2 button to be reported for the pen tool. */
+		wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
+	} else {
+		/* report proximity-out of a (valid) tool */
+		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+			/* Unknown tool selected default to pen tool */
+			wacom->tool[1] = BTN_TOOL_PEN;
+		}
+		wacom_report_key(wcombo, wacom->tool[1], prox);
+	}
+
+	wacom->tool[0] = prox; /* Save proximity state */
+	return 1;
+}
+
+static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
+{
+	unsigned char *data = wacom->data;
+	int id;
+
+	if (data[0] != 2) {
+		printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
+		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);
+		id = ERASER_DEVICE_ID;
+	} else {
+		wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20);
+		wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
+		id = STYLUS_DEVICE_ID;
+	}
+	wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+	wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+	wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+	wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
+	wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+	wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
+	return 1;
+}
+
+static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
+{
+	unsigned char *data = wacom->data;
+	int x, y, id, rw;
+
+	if (data[0] != 2) {
+		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
+		return 0;
+	}
+
+	wacom_input_regs(wcombo);
+
+	id = STYLUS_DEVICE_ID;
+	if (data[1] & 0x10) { /* in prox */
+
+		switch ((data[1] >> 5) & 3) {
+
+			case 0:	/* Pen */
+				wacom->tool[0] = BTN_TOOL_PEN;
+				break;
+
+			case 1: /* Rubber */
+				wacom->tool[0] = BTN_TOOL_RUBBER;
+				id = ERASER_DEVICE_ID;
+				break;
+
+			case 2: /* Mouse with wheel */
+				wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
+				if (wacom->features->type == WACOM_G4) {
+					rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
+					wacom_report_rel(wcombo, REL_WHEEL, -rw);
+				} else
+					wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]);
+				/* fall through */
+
+			case 3: /* Mouse without wheel */
+				wacom->tool[0] = BTN_TOOL_MOUSE;
+				id = CURSOR_DEVICE_ID;
+				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]);
+				else
+					wacom_report_abs(wcombo, ABS_DISTANCE, data[7]);
+				break;
+		}
+	}
+
+	if (data[1] & 0x90) {
+		x = wacom_le16_to_cpu(&data[2]);
+		y = wacom_le16_to_cpu(&data[4]);
+		wacom_report_abs(wcombo, ABS_X, x);
+		wacom_report_abs(wcombo, ABS_Y, y);
+		if (wacom->tool[0] != BTN_TOOL_MOUSE) {
+			wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
+			wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
+			wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
+		}
+	}
+
+	if (data[1] & 0x10)
+		wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+	else
+		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+	wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10);
+	wacom_input_sync(wcombo);
+
+	/* send pad data */
+	if (wacom->features->type == WACOM_G4) {
+		if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) {
+			wacom->id[1] = 1;
+			wacom->serial[1] = (data[7] & 0xf8);
+			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
+			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
+			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
+			wacom_report_rel(wcombo, REL_WHEEL, rw);
+			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+		} else if (wacom->id[1]) {
+			wacom->id[1] = 0;
+			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+		}
+	}
+	return 1;
+}
+
+static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
+{
+	unsigned char *data = wacom->data;
+	int idx;
+
+	/* tool number */
+	idx = data[1] & 0x01;
+
+	/* Enter report */
+	if ((data[1] & 0xfc) == 0xc0) {
+		/* serial number of the tool */
+		wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+			(data[4] << 20) + (data[5] << 12) +
+			(data[6] << 4) + (data[7] >> 4);
+
+		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
+		switch (wacom->id[idx]) {
+			case 0x812: /* Inking pen */
+			case 0x801: /* Intuos3 Inking pen */
+			case 0x012:
+				wacom->tool[idx] = BTN_TOOL_PENCIL;
+				break;
+			case 0x822: /* Pen */
+			case 0x842:
+			case 0x852:
+			case 0x823: /* Intuos3 Grip Pen */
+			case 0x813: /* Intuos3 Classic Pen */
+			case 0x885: /* Intuos3 Marker Pen */
+			case 0x022:
+				wacom->tool[idx] = BTN_TOOL_PEN;
+				break;
+			case 0x832: /* Stroke pen */
+			case 0x032:
+				wacom->tool[idx] = BTN_TOOL_BRUSH;
+				break;
+			case 0x007: /* Mouse 4D and 2D */
+		        case 0x09c:
+			case 0x094:
+			case 0x017: /* Intuos3 2D Mouse */
+				wacom->tool[idx] = BTN_TOOL_MOUSE;
+				break;
+			case 0x096: /* Lens cursor */
+			case 0x097: /* Intuos3 Lens cursor */
+				wacom->tool[idx] = BTN_TOOL_LENS;
+				break;
+			case 0x82a: /* Eraser */
+			case 0x85a:
+		        case 0x91a:
+			case 0xd1a:
+			case 0x0fa:
+			case 0x82b: /* Intuos3 Grip Pen Eraser */
+			case 0x81b: /* Intuos3 Classic Pen Eraser */
+			case 0x91b: /* Intuos3 Airbrush Eraser */
+				wacom->tool[idx] = BTN_TOOL_RUBBER;
+				break;
+			case 0xd12:
+			case 0x912:
+			case 0x112:
+			case 0x913: /* Intuos3 Airbrush */
+				wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
+				break;
+			default: /* Unknown tool */
+				wacom->tool[idx] = BTN_TOOL_PEN;
+		}
+		/* only large I3 support Lens Cursor */
+		if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
+				(wacom->features->type == INTUOS3))) {
+			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]);
+			return 2;
+		}
+		return 1;
+	}
+
+	/* 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;
+	}
+	return 0;
+}
+
+static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
+{
+	unsigned char *data = wacom->data;
+	unsigned int t;
+
+	/* general pen packet */
+	if ((data[1] & 0xb8) == 0xa0) {
+		t = (data[6] << 2) | ((data[7] >> 6) & 3);
+		wacom_report_abs(wcombo, ABS_PRESSURE, t);
+		wacom_report_abs(wcombo, ABS_TILT_X,
+				((data[7] << 1) & 0x7e) | (data[8] >> 7));
+		wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+		wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2);
+		wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4);
+		wacom_report_key(wcombo, BTN_TOUCH, t > 10);
+	}
+
+	/* airbrush second packet */
+	if ((data[1] & 0xbc) == 0xb4) {
+		wacom_report_abs(wcombo, ABS_WHEEL,
+				(data[6] << 2) | ((data[7] >> 6) & 3));
+		wacom_report_abs(wcombo, ABS_TILT_X,
+				((data[7] << 1) & 0x7e) | (data[8] >> 7));
+		wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+	}
+	return;
+}
+
+static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
+{
+	unsigned char *data = wacom->data;
+	unsigned int t;
+	int idx, result;
+
+	if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
+		dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
+                return 0;
+	}
+
+	wacom_input_regs(wcombo);
+
+	/* tool number */
+	idx = data[1] & 0x01;
+
+	/* pad packets. Works as a second tool and is always in prox */
+	if (data[0] == 12) {
+		/* initiate the pad as a device */
+		if (wacom->tool[1] != BTN_TOOL_FINGER)
+			wacom->tool[1] = BTN_TOOL_FINGER;
+
+		wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
+		wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
+		wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
+		wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
+		wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
+		wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
+		wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
+		wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
+		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])
+			wacom_report_key(wcombo, wacom->tool[1], 1);
+		else
+			wacom_report_key(wcombo, wacom->tool[1], 0);
+		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
+                return 1;
+	}
+
+	/* process in/out prox events */
+	result = wacom_intuos_inout(wacom, wcombo);
+	if (result)
+                return result-1;
+
+	/* Cintiq doesn't send data when RDY bit isn't set */
+	if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
+                 return 0;
+
+	if (wacom->features->type >= INTUOS3) {
+		wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
+		wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
+		wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
+	} else {
+		wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2]));
+		wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4]));
+		wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
+	}
+
+	/* process general packets */
+	wacom_intuos_general(wacom, wcombo);
+
+	/* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
+	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
+
+		if (data[1] & 0x02) {
+			/* Rotation packet */
+			if (wacom->features->type >= INTUOS3) {
+				/* I3 marker pen rotation reported as wheel
+				 * due to valuator limitation
+				 */
+				t = (data[6] << 3) | ((data[7] >> 5) & 7);
+				t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+					((t-1) / 2 + 450)) : (450 - t / 2) ;
+				wacom_report_abs(wcombo, ABS_WHEEL, t);
+			} else {
+				/* 4D mouse rotation packet */
+				t = (data[6] << 3) | ((data[7] >> 5) & 7);
+				wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ?
+					((t - 1) / 2) : -t / 2);
+			}
+
+		} else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
+			/* 4D mouse packet */
+			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
+			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
+			wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
+
+			wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x20);
+			wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x10);
+			t = (data[6] << 2) | ((data[7] >> 6) & 3);
+			wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
+
+		} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
+			/* 2D mouse packet */
+			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04);
+			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
+			wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10);
+			wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
+						 - ((data[8] & 0x02) >> 1));
+
+			/* I3 2D mouse side buttons */
+			if (wacom->features->type == INTUOS3) {
+				wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
+				wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
+			}
+
+		} else if (wacom->features->type < INTUOS3) {
+			/* Lens cursor packets */
+			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
+			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
+			wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
+			wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x10);
+			wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x08);
+		}
+	}
+
+	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]);
+	return 1;
+}
+
+int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
+{
+	switch (wacom_wac->features->type) {
+		case PENPARTNER:
+			return (wacom_penpartner_irq(wacom_wac, wcombo));
+			break;
+		case PL:
+			return (wacom_pl_irq(wacom_wac, wcombo));
+			break;
+		case WACOM_G4:
+		case GRAPHIRE:
+			return (wacom_graphire_irq(wacom_wac, wcombo));
+			break;
+		case PTU:
+			return (wacom_ptu_irq(wacom_wac, wcombo));
+			break;
+		case INTUOS:
+		case INTUOS3:
+		case INTUOS3L:
+		case CINTIQ:
+			return (wacom_intuos_irq(wacom_wac, wcombo));
+			break;
+		default:
+			return 0;
+	}
+	return 0;
+}
+
+void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	switch (wacom_wac->features->type) {
+		case WACOM_G4:
+			input_dev_g4(input_dev, wacom_wac);
+			/* fall through */
+		case GRAPHIRE:
+			input_dev_g(input_dev, wacom_wac);
+			break;
+		case INTUOS3:
+		case INTUOS3L:
+		case CINTIQ:
+			input_dev_i3(input_dev, wacom_wac);
+			/* fall through */
+		case INTUOS:
+			input_dev_i(input_dev, wacom_wac);
+			break;
+		case PL:
+		case PTU:
+			input_dev_pl(input_dev, wacom_wac);
+			break;
+		case PENPARTNER:
+			input_dev_pt(input_dev, wacom_wac);
+			break;
+	}
+	return;
+}
+
+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 },
+	{ }
+};
+
+static struct usb_device_id wacom_ids[] = {
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
+	{ 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, 0x3F) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
+	{ }
+};
+
+const struct usb_device_id * get_device_table(void) {
+        const struct usb_device_id * id_table = wacom_ids;
+        return id_table;
+}
+
+struct wacom_features * get_wacom_feature(const struct usb_device_id * id) {
+        int index = id - wacom_ids;
+        struct wacom_features *wf = &wacom_features[index];
+        return wf;
+}
+
+MODULE_DEVICE_TABLE(usb, wacom_ids);
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h
new file mode 100644
index 0000000..ceae7bf
--- /dev/null
+++ b/drivers/usb/input/wacom_wac.h
@@ -0,0 +1,48 @@
+/*
+ * drivers/usb/input/wacom_wac.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef WACOM_WAC_H
+#define WACOM_WAC_H
+
+#define STYLUS_DEVICE_ID	0x02
+#define CURSOR_DEVICE_ID	0x06
+#define ERASER_DEVICE_ID	0x0A
+
+enum {
+	PENPARTNER = 0,
+	GRAPHIRE,
+	WACOM_G4,
+	PTU,
+	PL,
+	INTUOS,
+	INTUOS3,
+	INTUOS3L,
+	CINTIQ,
+	MAX_TYPE
+};
+
+struct wacom_features {
+	char *name;
+	int pktlen;
+	int x_max;
+	int y_max;
+	int pressure_max;
+	int distance_max;
+	int type;
+	usb_complete_t irq;
+};
+
+struct wacom_wac {
+	signed char *data;
+        int tool[2];
+        int id[2];
+        __u32 serial[2];
+	struct wacom_features *features;
+};
+
+#endif
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 7b45fd3..7291e7a 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -971,7 +971,7 @@
 			DRIVER_VERSION, sizeof(DRIVER_VERSION));
 
 	/* Register sysfs hooks (don't care about failure) */
-	sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
+	ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
 	return 0;
 }
 
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 88928a4..c29658f 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -32,6 +32,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called emi26.
 
+config USB_ADUTUX
+	tristate "ADU devices from Ontrak Control Systems (EXPERIMENTAL)"
+	depends on USB && EXPERIMENTAL
+	help
+	  Say Y if you want to use an ADU device from Ontrak Control
+	  Systems.
+
+	  To compile this driver as a module, choose M here.  The module
+	  will be called adutux.
+
 config USB_AUERSWALD
 	tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
 	depends on USB && EXPERIMENTAL
@@ -115,19 +125,36 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cytherm.
 
-config USB_PHIDGETKIT
-	tristate "USB PhidgetKit support"
+config USB_PHIDGET
+	tristate "USB Phidgets drivers"
 	depends on USB
 	help
-	  Say Y here if you want to connect a PhidgetKit USB device from
-	  Phidgets Inc.
+	  Say Y here to enable the various drivers for devices from
+	  Phidgets inc.
+
+config USB_PHIDGETKIT
+	tristate "USB PhidgetInterfaceKit support"
+	depends on USB_PHIDGET
+	help
+	  Say Y here if you want to connect a PhidgetInterfaceKit USB device
+	  from Phidgets Inc.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called phidgetkit.
 
+config USB_PHIDGETMOTORCONTROL
+	tristate "USB PhidgetMotorControl support"
+	depends on USB_PHIDGET
+	help
+	  Say Y here if you want to connect a PhidgetMotorControl USB device
+	  from Phidgets Inc.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called phidgetmotorcontrol.
+
 config USB_PHIDGETSERVO
 	tristate "USB PhidgetServo support"
-	depends on USB
+	depends on USB_PHIDGET
 	help
 	  Say Y here if you want to connect an 1 or 4 Motor PhidgetServo 
 	  servo controller version 2.0 or 3.0.
@@ -151,6 +178,30 @@
 
 	  See also <http://www.fs.tum.de/~echtler/idmouse/>.
 
+config USB_FTDI_ELAN
+	tristate "Elan PCMCIA CardBus Adapter USB Client"
+	depends on USB
+	default M
+	help
+	  ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters.
+	  Currently only the U132 adapter is available.
+
+	  The U132 is specifically designed for CardBus PC cards that contain
+	  an OHCI host controller. Typical PC cards are the Orange Mobile 3G
+	  Option GlobeTrotter Fusion card. The U132 adapter will *NOT* work
+	  with PC cards that do not contain an OHCI controller. To use a U132
+	  adapter you will need this "ftdi-elan" module as well as the "u132-hcd"
+	  module which is a USB host controller driver that talks to the OHCI
+	  controller within CardBus card that are inserted in the U132 adapter.
+
+	  This driver has been tested with a CardBus OHCI USB adapter, and
+	  worked with a USB PEN Drive inserted into the first USB port of
+	  the PCCARD. A rather pointless thing to do, but useful for testing.
+
+	  See also the USB_U132_HCD entry "Elan U132 Adapter Host Controller"
+
+	  It is safe to say M here.
+
 config USB_APPLEDISPLAY
 	tristate "Apple Cinema Display support"
 	depends on USB
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 2927260..2be70fa 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -3,22 +3,25 @@
 # (the ones that don't fit into any other categories)
 #
 
+obj-$(CONFIG_USB_ADUTUX)	+= adutux.o
 obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
 obj-$(CONFIG_USB_EMI26)		+= emi26.o
 obj-$(CONFIG_USB_EMI62)		+= emi62.o
+obj-$(CONFIG_USB_FTDI_ELAN)	+= ftdi-elan.o
 obj-$(CONFIG_USB_IDMOUSE)	+= idmouse.o
 obj-$(CONFIG_USB_LCD)		+= usblcd.o
 obj-$(CONFIG_USB_LD)		+= ldusb.o
 obj-$(CONFIG_USB_LED)		+= usbled.o
 obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
+obj-$(CONFIG_USB_PHIDGET)	+= phidget.o
 obj-$(CONFIG_USB_PHIDGETKIT)	+= phidgetkit.o
+obj-$(CONFIG_USB_PHIDGETMOTORCONTROL)	+= phidgetmotorcontrol.o
 obj-$(CONFIG_USB_PHIDGETSERVO)	+= phidgetservo.o
 obj-$(CONFIG_USB_RIO500)	+= rio500.o
 obj-$(CONFIG_USB_TEST)		+= usbtest.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
-obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
 
 obj-$(CONFIG_USB_SISUSBVGA)	+= sisusbvga/
 
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
new file mode 100644
index 0000000..d396319
--- /dev/null
+++ b/drivers/usb/misc/adutux.c
@@ -0,0 +1,900 @@
+/*
+ * adutux - driver for ADU devices from Ontrak Control Systems
+ * This is an experimental driver. Use at your own risk.
+ * This driver is not supported by Ontrak Control Systems.
+ *
+ * Copyright (c) 2003 John Homppi (SCO, leave this notice here)
+ *
+ * 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.
+ *
+ * derived from the Lego USB Tower driver 0.56:
+ * Copyright (c) 2003 David Glance <davidgsf@sourceforge.net>
+ *               2001 Juergen Stuber <stuber@loria.fr>
+ * that was derived from USB Skeleton driver - 0.5
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_USB_DEBUG
+static int debug = 5;
+#else
+static int debug = 1;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(lvl, format, arg...) 					\
+do { 									\
+	if (debug >= lvl)						\
+		printk(KERN_DEBUG __FILE__ " : " format " \n", ## arg);	\
+} while (0)
+
+
+/* Version Information */
+#define DRIVER_VERSION "v0.0.13"
+#define DRIVER_AUTHOR "John Homppi"
+#define DRIVER_DESC "adutux (see www.ontrak.net)"
+
+/* Module parameters */
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+/* Define these values to match your device */
+#define ADU_VENDOR_ID 0x0a07
+#define ADU_PRODUCT_ID 0x0064
+
+/* table of devices that work with this driver */
+static struct usb_device_id device_table [] = {
+	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) },		/* ADU100 */
+	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, 	/* ADU120 */
+	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, 	/* ADU130 */
+	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) },	/* ADU200 */
+	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) },	/* ADU208 */
+	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) },	/* ADU218 */
+	{ }/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define ADU_MINOR_BASE	0
+#else
+#define ADU_MINOR_BASE	67
+#endif
+
+/* we can have up to this number of device plugged in at once */
+#define MAX_DEVICES	16
+
+#define COMMAND_TIMEOUT	(2*HZ)	/* 60 second timeout for a command */
+
+/* Structure to hold all of our device specific stuff */
+struct adu_device {
+	struct semaphore	sem; /* locks this structure */
+	struct usb_device*	udev; /* save off the usb device pointer */
+	struct usb_interface*	interface;
+	unsigned char		minor; /* the starting minor number for this device */
+	char			serial_number[8];
+
+	int			open_count; /* number of times this port has been opened */
+
+	char*			read_buffer_primary;
+	int			read_buffer_length;
+	char*			read_buffer_secondary;
+	int			secondary_head;
+	int			secondary_tail;
+	spinlock_t		buflock;
+
+	wait_queue_head_t	read_wait;
+	wait_queue_head_t	write_wait;
+
+	char*			interrupt_in_buffer;
+	struct usb_endpoint_descriptor* interrupt_in_endpoint;
+	struct urb*		interrupt_in_urb;
+	int			read_urb_finished;
+
+	char*			interrupt_out_buffer;
+	struct usb_endpoint_descriptor* interrupt_out_endpoint;
+	struct urb*		interrupt_out_urb;
+};
+
+/* prevent races between open() and disconnect */
+static DEFINE_MUTEX(disconnect_mutex);
+static struct usb_driver adu_driver;
+
+static void adu_debug_data(int level, const char *function, int size,
+			   const unsigned char *data)
+{
+	int i;
+
+	if (debug < level)
+		return;
+
+	printk(KERN_DEBUG __FILE__": %s - length = %d, data = ",
+	       function, size);
+	for (i = 0; i < size; ++i)
+		printk("%.2x ", data[i]);
+	printk("\n");
+}
+
+/**
+ * adu_abort_transfers
+ *      aborts transfers and frees associated data structures
+ */
+static void adu_abort_transfers(struct adu_device *dev)
+{
+	dbg(2," %s : enter", __FUNCTION__);
+
+	if (dev == NULL) {
+		dbg(1," %s : dev is null", __FUNCTION__);
+		goto exit;
+	}
+
+	if (dev->udev == NULL) {
+		dbg(1," %s : udev is null", __FUNCTION__);
+		goto exit;
+	}
+
+	dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state);
+	if (dev->udev->state == USB_STATE_NOTATTACHED) {
+		dbg(1," %s : udev is not attached", __FUNCTION__);
+		goto exit;
+	}
+
+	/* shutdown transfer */
+	usb_unlink_urb(dev->interrupt_in_urb);
+	usb_unlink_urb(dev->interrupt_out_urb);
+
+exit:
+	dbg(2," %s : leave", __FUNCTION__);
+}
+
+static void adu_delete(struct adu_device *dev)
+{
+	dbg(2, "%s enter", __FUNCTION__);
+
+	adu_abort_transfers(dev);
+
+	/* free data structures */
+	usb_free_urb(dev->interrupt_in_urb);
+	usb_free_urb(dev->interrupt_out_urb);
+	kfree(dev->read_buffer_primary);
+	kfree(dev->read_buffer_secondary);
+	kfree(dev->interrupt_in_buffer);
+	kfree(dev->interrupt_out_buffer);
+	kfree(dev);
+
+	dbg(2, "%s : leave", __FUNCTION__);
+}
+
+static void adu_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct adu_device *dev = urb->context;
+
+	dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+	adu_debug_data(5, __FUNCTION__, urb->actual_length,
+		       urb->transfer_buffer);
+
+	spin_lock(&dev->buflock);
+
+	if (urb->status != 0) {
+		if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) {
+			dbg(1," %s : nonzero status received: %d",
+			    __FUNCTION__, urb->status);
+		}
+		goto exit;
+	}
+
+	if (urb->actual_length > 0 && dev->interrupt_in_buffer[0] != 0x00) {
+		if (dev->read_buffer_length <
+		    (4 * le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize)) -
+		     (urb->actual_length)) {
+			memcpy (dev->read_buffer_primary +
+				dev->read_buffer_length,
+				dev->interrupt_in_buffer, urb->actual_length);
+
+			dev->read_buffer_length += urb->actual_length;
+			dbg(2," %s reading  %d ", __FUNCTION__,
+			    urb->actual_length);
+		} else {
+			dbg(1," %s : read_buffer overflow", __FUNCTION__);
+		}
+	}
+
+exit:
+	dev->read_urb_finished = 1;
+	spin_unlock(&dev->buflock);
+	/* always wake up so we recover from errors */
+	wake_up_interruptible(&dev->read_wait);
+	adu_debug_data(5, __FUNCTION__, urb->actual_length,
+		       urb->transfer_buffer);
+	dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+}
+
+static void adu_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct adu_device *dev = urb->context;
+
+	dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+	adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
+
+	if (urb->status != 0) {
+		if ((urb->status != -ENOENT) &&
+		    (urb->status != -ECONNRESET)) {
+			dbg(1, " %s :nonzero status received: %d",
+			    __FUNCTION__, urb->status);
+		}
+		goto exit;
+	}
+
+	wake_up_interruptible(&dev->write_wait);
+exit:
+
+	adu_debug_data(5, __FUNCTION__, urb->actual_length,
+		       urb->transfer_buffer);
+	dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+}
+
+static int adu_open(struct inode *inode, struct file *file)
+{
+	struct adu_device *dev = NULL;
+	struct usb_interface *interface;
+	int subminor;
+	int retval = 0;
+
+	dbg(2,"%s : enter", __FUNCTION__);
+
+	subminor = iminor(inode);
+
+	mutex_lock(&disconnect_mutex);
+
+	interface = usb_find_interface(&adu_driver, subminor);
+	if (!interface) {
+		err("%s - error, can't find device for minor %d",
+		    __FUNCTION__, subminor);
+		retval = -ENODEV;
+		goto exit_no_device;
+	}
+
+	dev = usb_get_intfdata(interface);
+	if (!dev) {
+		retval = -ENODEV;
+		goto exit_no_device;
+	}
+
+	/* lock this device */
+	if ((retval = down_interruptible(&dev->sem))) {
+		dbg(2, "%s : sem down failed", __FUNCTION__);
+		goto exit_no_device;
+	}
+
+	/* increment our usage count for the device */
+	++dev->open_count;
+	dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
+
+	/* save device in the file's private structure */
+	file->private_data = dev;
+
+	/* initialize in direction */
+	dev->read_buffer_length = 0;
+
+	/* fixup first read by having urb waiting for it */
+	usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+			 usb_rcvintpipe(dev->udev,
+			 		dev->interrupt_in_endpoint->bEndpointAddress),
+			 dev->interrupt_in_buffer,
+			 le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+			 adu_interrupt_in_callback, dev,
+			 dev->interrupt_in_endpoint->bInterval);
+	/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+	dev->read_urb_finished = 0;
+	usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+	/* we ignore failure */
+	/* end of fixup for first read */
+
+	up(&dev->sem);
+
+exit_no_device:
+	mutex_unlock(&disconnect_mutex);
+	dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
+
+	return retval;
+}
+
+static int adu_release_internal(struct adu_device *dev)
+{
+	int retval = 0;
+
+	dbg(2," %s : enter", __FUNCTION__);
+
+	if (dev->udev == NULL) {
+		/* the device was unplugged before the file was released */
+		adu_delete(dev);
+		goto exit;
+	}
+
+	/* decrement our usage count for the device */
+	--dev->open_count;
+	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+	if (dev->open_count <= 0) {
+		adu_abort_transfers(dev);
+		dev->open_count = 0;
+	}
+
+exit:
+	dbg(2," %s : leave", __FUNCTION__);
+	return retval;
+}
+
+static int adu_release(struct inode *inode, struct file *file)
+{
+	struct adu_device *dev = NULL;
+	int retval = 0;
+
+	dbg(2," %s : enter", __FUNCTION__);
+
+	if (file == NULL) {
+ 		dbg(1," %s : file is NULL", __FUNCTION__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	dev = file->private_data;
+
+	if (dev == NULL) {
+ 		dbg(1," %s : object is NULL", __FUNCTION__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	/* lock our device */
+	down(&dev->sem); /* not interruptible */
+
+	if (dev->open_count <= 0) {
+		dbg(1," %s : device not opened", __FUNCTION__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	/* do the work */
+	retval = adu_release_internal(dev);
+
+exit:
+	up(&dev->sem);
+	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+	return retval;
+}
+
+static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+			loff_t *ppos)
+{
+	struct adu_device *dev;
+	size_t bytes_read = 0;
+	size_t bytes_to_read = count;
+	int i;
+	int retval = 0;
+	int timeout = 0;
+	int should_submit = 0;
+	unsigned long flags;
+	DECLARE_WAITQUEUE(wait, current);
+
+	dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
+
+	dev = file->private_data;
+	dbg(2," %s : dev=%p", __FUNCTION__, dev);
+	/* lock this object */
+	if (down_interruptible(&dev->sem))
+		return -ERESTARTSYS;
+
+	/* verify that the device wasn't unplugged */
+	if (dev->udev == NULL || dev->minor == 0) {
+		retval = -ENODEV;
+		err("No device or device unplugged %d", retval);
+		goto exit;
+	}
+
+	/* verify that some data was requested */
+	if (count == 0) {
+		dbg(1," %s : read request of 0 bytes", __FUNCTION__);
+		goto exit;
+	}
+
+	timeout = COMMAND_TIMEOUT;
+	dbg(2," %s : about to start looping", __FUNCTION__);
+	while (bytes_to_read) {
+		int data_in_secondary = dev->secondary_tail - dev->secondary_head;
+		dbg(2," %s : while, data_in_secondary=%d, status=%d",
+		    __FUNCTION__, data_in_secondary,
+		    dev->interrupt_in_urb->status);
+
+		if (data_in_secondary) {
+			/* drain secondary buffer */
+			int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary;
+			i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount);
+			if (i < 0) {
+				retval = -EFAULT;
+				goto exit;
+			}
+			dev->secondary_head += (amount - i);
+			bytes_read += (amount - i);
+			bytes_to_read -= (amount - i);
+			if (i) {
+				retval = bytes_read ? bytes_read : -EFAULT;
+				goto exit;
+			}
+		} else {
+			/* we check the primary buffer */
+			spin_lock_irqsave (&dev->buflock, flags);
+			if (dev->read_buffer_length) {
+				/* we secure access to the primary */
+				char *tmp;
+				dbg(2," %s : swap, read_buffer_length = %d",
+				    __FUNCTION__, dev->read_buffer_length);
+				tmp = dev->read_buffer_secondary;
+				dev->read_buffer_secondary = dev->read_buffer_primary;
+				dev->read_buffer_primary = tmp;
+				dev->secondary_head = 0;
+				dev->secondary_tail = dev->read_buffer_length;
+				dev->read_buffer_length = 0;
+				spin_unlock_irqrestore(&dev->buflock, flags);
+				/* we have a free buffer so use it */
+				should_submit = 1;
+			} else {
+				/* even the primary was empty - we may need to do IO */
+				if (dev->interrupt_in_urb->status == -EINPROGRESS) {
+					/* somebody is doing IO */
+					spin_unlock_irqrestore(&dev->buflock, flags);
+					dbg(2," %s : submitted already", __FUNCTION__);
+				} else {
+					/* we must initiate input */
+					dbg(2," %s : initiate input", __FUNCTION__);
+					dev->read_urb_finished = 0;
+
+					usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+							 usb_rcvintpipe(dev->udev,
+							 		dev->interrupt_in_endpoint->bEndpointAddress),
+							 dev->interrupt_in_buffer,
+							 le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+							 adu_interrupt_in_callback,
+							 dev,
+							 dev->interrupt_in_endpoint->bInterval);
+					retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+					if (!retval) {
+						spin_unlock_irqrestore(&dev->buflock, flags);
+						dbg(2," %s : submitted OK", __FUNCTION__);
+					} else {
+						if (retval == -ENOMEM) {
+							retval = bytes_read ? bytes_read : -ENOMEM;
+						}
+						spin_unlock_irqrestore(&dev->buflock, flags);
+						dbg(2," %s : submit failed", __FUNCTION__);
+						goto exit;
+					}
+				}
+
+				/* we wait for I/O to complete */
+				set_current_state(TASK_INTERRUPTIBLE);
+				add_wait_queue(&dev->read_wait, &wait);
+				if (!dev->read_urb_finished)
+					timeout = schedule_timeout(COMMAND_TIMEOUT);
+				else
+					set_current_state(TASK_RUNNING);
+				remove_wait_queue(&dev->read_wait, &wait);
+
+				if (timeout <= 0) {
+					dbg(2," %s : timeout", __FUNCTION__);
+					retval = bytes_read ? bytes_read : -ETIMEDOUT;
+					goto exit;
+				}
+
+				if (signal_pending(current)) {
+					dbg(2," %s : signal pending", __FUNCTION__);
+					retval = bytes_read ? bytes_read : -EINTR;
+					goto exit;
+				}
+			}
+		}
+	}
+
+	retval = bytes_read;
+	/* if the primary buffer is empty then use it */
+	if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) {
+		usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+				 usb_rcvintpipe(dev->udev,
+				 		dev->interrupt_in_endpoint->bEndpointAddress),
+						dev->interrupt_in_buffer,
+						le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+						adu_interrupt_in_callback,
+						dev,
+						dev->interrupt_in_endpoint->bInterval);
+		/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+		dev->read_urb_finished = 0;
+		usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+		/* we ignore failure */
+	}
+
+exit:
+	/* unlock the device */
+	up(&dev->sem);
+
+	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+	return retval;
+}
+
+static ssize_t adu_write(struct file *file, const __user char *buffer,
+			 size_t count, loff_t *ppos)
+{
+	struct adu_device *dev;
+	size_t bytes_written = 0;
+	size_t bytes_to_write;
+	size_t buffer_size;
+	int retval = 0;
+	int timeout = 0;
+
+	dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
+
+	dev = file->private_data;
+
+	/* lock this object */
+	down_interruptible(&dev->sem);
+
+	/* verify that the device wasn't unplugged */
+	if (dev->udev == NULL || dev->minor == 0) {
+		retval = -ENODEV;
+		err("No device or device unplugged %d", retval);
+		goto exit;
+	}
+
+	/* verify that we actually have some data to write */
+	if (count == 0) {
+		dbg(1," %s : write request of 0 bytes", __FUNCTION__);
+		goto exit;
+	}
+
+
+	while (count > 0) {
+		if (dev->interrupt_out_urb->status == -EINPROGRESS) {
+			timeout = COMMAND_TIMEOUT;
+
+			while (timeout > 0) {
+				if (signal_pending(current)) {
+				dbg(1," %s : interrupted", __FUNCTION__);
+				retval = -EINTR;
+				goto exit;
+			}
+			up(&dev->sem);
+			timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout);
+			down_interruptible(&dev->sem);
+			if (timeout > 0) {
+				break;
+			}
+			dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout);
+		}
+
+
+		dbg(1," %s : final timeout: %d", __FUNCTION__, timeout);
+
+		if (timeout == 0) {
+			dbg(1, "%s - command timed out.", __FUNCTION__);
+			retval = -ETIMEDOUT;
+			goto exit;
+		}
+
+		dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
+
+		} else {
+			dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
+
+			/* write the data into interrupt_out_buffer from userspace */
+			buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+			bytes_to_write = count > buffer_size ? buffer_size : count;
+			dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd",
+			    __FUNCTION__, buffer_size, count, bytes_to_write);
+
+			if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
+				retval = -EFAULT;
+				goto exit;
+			}
+
+			/* send off the urb */
+			usb_fill_int_urb(
+				dev->interrupt_out_urb,
+				dev->udev,
+				usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress),
+				dev->interrupt_out_buffer,
+				bytes_to_write,
+				adu_interrupt_out_callback,
+				dev,
+				dev->interrupt_in_endpoint->bInterval);
+			/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+			dev->interrupt_out_urb->actual_length = bytes_to_write;
+			retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
+			if (retval < 0) {
+				err("Couldn't submit interrupt_out_urb %d", retval);
+				goto exit;
+			}
+
+			buffer += bytes_to_write;
+			count -= bytes_to_write;
+
+			bytes_written += bytes_to_write;
+		}
+	}
+
+	retval = bytes_written;
+
+exit:
+	/* unlock the device */
+	up(&dev->sem);
+
+	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+
+	return retval;
+}
+
+/* file operations needed when we register this driver */
+static struct file_operations adu_fops = {
+	.owner = THIS_MODULE,
+	.read  = adu_read,
+	.write = adu_write,
+	.open = adu_open,
+	.release = adu_release,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver adu_class = {
+	.name = "usb/adutux%d",
+	.fops = &adu_fops,
+	.minor_base = ADU_MINOR_BASE,
+};
+
+/**
+ * adu_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int adu_probe(struct usb_interface *interface,
+		     const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct adu_device *dev = NULL;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int retval = -ENODEV;
+	int in_end_size;
+	int out_end_size;
+	int i;
+
+	dbg(2," %s : enter", __FUNCTION__);
+
+	if (udev == NULL) {
+		dev_err(&interface->dev, "udev is NULL.\n");
+		goto exit;
+	}
+
+	/* allocate memory for our device state and intialize it */
+	dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "Out of memory\n");
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	init_MUTEX(&dev->sem);
+	spin_lock_init(&dev->buflock);
+	dev->udev = udev;
+	init_waitqueue_head(&dev->read_wait);
+	init_waitqueue_head(&dev->write_wait);
+
+	iface_desc = &interface->altsetting[0];
+
+	/* set up the endpoint information */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_int_in(endpoint))
+			dev->interrupt_in_endpoint = endpoint;
+
+		if (usb_endpoint_is_int_out(endpoint))
+			dev->interrupt_out_endpoint = endpoint;
+	}
+	if (dev->interrupt_in_endpoint == NULL) {
+		dev_err(&interface->dev, "interrupt in endpoint not found\n");
+		goto error;
+	}
+	if (dev->interrupt_out_endpoint == NULL) {
+		dev_err(&interface->dev, "interrupt out endpoint not found\n");
+		goto error;
+	}
+
+	in_end_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
+	out_end_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+
+	dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL);
+	if (!dev->read_buffer_primary) {
+		dev_err(&interface->dev, "Couldn't allocate read_buffer_primary\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	/* debug code prime the buffer */
+	memset(dev->read_buffer_primary, 'a', in_end_size);
+	memset(dev->read_buffer_primary + in_end_size, 'b', in_end_size);
+	memset(dev->read_buffer_primary + (2 * in_end_size), 'c', in_end_size);
+	memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size);
+
+	dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL);
+	if (!dev->read_buffer_secondary) {
+		dev_err(&interface->dev, "Couldn't allocate read_buffer_secondary\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	/* debug code prime the buffer */
+	memset(dev->read_buffer_secondary, 'e', in_end_size);
+	memset(dev->read_buffer_secondary + in_end_size, 'f', in_end_size);
+	memset(dev->read_buffer_secondary + (2 * in_end_size), 'g', in_end_size);
+	memset(dev->read_buffer_secondary + (3 * in_end_size), 'h', in_end_size);
+
+	dev->interrupt_in_buffer = kmalloc(in_end_size, GFP_KERNEL);
+	if (!dev->interrupt_in_buffer) {
+		dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
+		goto error;
+	}
+
+	/* debug code prime the buffer */
+	memset(dev->interrupt_in_buffer, 'i', in_end_size);
+
+	dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->interrupt_in_urb) {
+		dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");
+		goto error;
+	}
+	dev->interrupt_out_buffer = kmalloc(out_end_size, GFP_KERNEL);
+	if (!dev->interrupt_out_buffer) {
+		dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
+		goto error;
+	}
+	dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->interrupt_out_urb) {
+		dev_err(&interface->dev, "Couldn't allocate interrupt_out_urb\n");
+		goto error;
+	}
+
+	if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number,
+			sizeof(dev->serial_number))) {
+		dev_err(&interface->dev, "Could not retrieve serial number\n");
+		goto error;
+	}
+	dbg(2," %s : serial_number=%s", __FUNCTION__, dev->serial_number);
+
+	/* we can register the device now, as it is ready */
+	usb_set_intfdata(interface, dev);
+
+	retval = usb_register_dev(interface, &adu_class);
+
+	if (retval) {
+		/* something prevented us from registering this driver */
+		dev_err(&interface->dev, "Not able to get a minor for this device.\n");
+		usb_set_intfdata(interface, NULL);
+		goto error;
+	}
+
+	dev->minor = interface->minor;
+
+	/* let the user know what node this device is now attached to */
+	dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d",
+		 udev->descriptor.idProduct, dev->serial_number,
+		 (dev->minor - ADU_MINOR_BASE));
+exit:
+	dbg(2," %s : leave, return value %p (dev)", __FUNCTION__, dev);
+
+	return retval;
+
+error:
+	adu_delete(dev);
+	return retval;
+}
+
+/**
+ * adu_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ */
+static void adu_disconnect(struct usb_interface *interface)
+{
+	struct adu_device *dev;
+	int minor;
+
+	dbg(2," %s : enter", __FUNCTION__);
+
+	mutex_lock(&disconnect_mutex); /* not interruptible */
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	down(&dev->sem); /* not interruptible */
+
+	minor = dev->minor;
+
+	/* give back our minor */
+	usb_deregister_dev(interface, &adu_class);
+	dev->minor = 0;
+
+	/* if the device is not opened, then we clean up right now */
+	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+	if (!dev->open_count) {
+		up(&dev->sem);
+		adu_delete(dev);
+	} else {
+		dev->udev = NULL;
+		up(&dev->sem);
+	}
+
+	mutex_unlock(&disconnect_mutex);
+
+	dev_info(&interface->dev, "ADU device adutux%d now disconnected",
+		 (minor - ADU_MINOR_BASE));
+
+	dbg(2," %s : leave", __FUNCTION__);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver adu_driver = {
+	.name = "adutux",
+	.probe = adu_probe,
+	.disconnect = adu_disconnect,
+	.id_table = device_table,
+};
+
+static int __init adu_init(void)
+{
+	int result;
+
+	dbg(2," %s : enter", __FUNCTION__);
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&adu_driver);
+	if (result < 0) {
+		err("usb_register failed for the "__FILE__" driver. "
+		    "Error number %d", result);
+		goto exit;
+	}
+
+	info("adutux " DRIVER_DESC " " DRIVER_VERSION);
+	info("adutux is an experimental driver. Use at your own risk");
+
+exit:
+	dbg(2," %s : leave, return value %d", __FUNCTION__, result);
+
+	return result;
+}
+
+static void __exit adu_exit(void)
+{
+	dbg(2," %s : enter", __FUNCTION__);
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&adu_driver);
+	dbg(2," %s : leave", __FUNCTION__);
+}
+
+module_init(adu_init);
+module_exit(adu_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 1fef36e..4fd2110 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -806,7 +806,7 @@
 0		Initial, OK
 -EINPROGRESS	during submission until end
 -ENOENT		if urb is unlinked
--ETIMEDOUT	Transfer timed out, NAK
+-ETIME		Device did not respond
 -ENOMEM		Memory Overflow
 -ENODEV		Specified USB-device or bus doesn't exist
 -ENXIO		URB already queued
@@ -832,7 +832,7 @@
 {
 	switch (status) {
 	case 0:
-	case -ETIMEDOUT:
+	case -ETIME:
 	case -EOVERFLOW:
 	case -EAGAIN:
 	case -EPIPE:
@@ -1858,7 +1858,7 @@
 
 /*----------------------------------------------------------------------*/
 /* File operation structure                                             */
-static struct file_operations auerswald_fops =
+static const struct file_operations auerswald_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index 9c46746..b63b5f3 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -209,7 +209,7 @@
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		dev_err(&interface->dev, "Out of memory!\n");
-		goto error;
+		goto error_mem;
 	}
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
@@ -218,15 +218,26 @@
 	usb_set_intfdata(interface, dev);
 
 	/* create device attribute files */
-	device_create_file(&interface->dev, &dev_attr_port0);
-	device_create_file(&interface->dev, &dev_attr_port1);
+	retval = device_create_file(&interface->dev, &dev_attr_port0);
+	if (retval)
+		goto error;
+	retval = device_create_file(&interface->dev, &dev_attr_port1);
+	if (retval)
+		goto error;
 
 	/* let the user know that the device is now attached */
 	dev_info(&interface->dev,
 		 "Cypress CY7C63xxx device now attached\n");
+	return 0;
 
-	retval = 0;
 error:
+	device_remove_file(&interface->dev, &dev_attr_port0);
+	device_remove_file(&interface->dev, &dev_attr_port1);
+	usb_set_intfdata(interface, NULL);
+	usb_put_dev(dev->udev);
+	kfree(dev);
+
+error_mem:
 	return retval;
 }
 
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index b20bec4..04e87ac 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -353,7 +353,7 @@
 	dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL);
 	if (dev == NULL) {
 		dev_err (&interface->dev, "Out of memory\n");
-		goto error;
+		goto error_mem;
 	}
 
 	dev->udev = usb_get_dev(udev);
@@ -362,18 +362,35 @@
 
 	dev->brightness = 0xFF;
 
-	device_create_file(&interface->dev, &dev_attr_brightness);   
-	device_create_file(&interface->dev, &dev_attr_temp);
-	device_create_file(&interface->dev, &dev_attr_button);
-	device_create_file(&interface->dev, &dev_attr_port0);
-	device_create_file(&interface->dev, &dev_attr_port1);
+	retval = device_create_file(&interface->dev, &dev_attr_brightness);
+	if (retval)
+		goto error;
+	retval = device_create_file(&interface->dev, &dev_attr_temp);
+	if (retval)
+		goto error;
+	retval = device_create_file(&interface->dev, &dev_attr_button);
+	if (retval)
+		goto error;
+	retval = device_create_file(&interface->dev, &dev_attr_port0);
+	if (retval)
+		goto error;
+	retval = device_create_file(&interface->dev, &dev_attr_port1);
+	if (retval)
+		goto error;
 
-	dev_info (&interface->dev, 
+	dev_info (&interface->dev,
 		  "Cypress thermometer device now attached\n");
 	return 0;
-
- error:
+error:
+	device_remove_file(&interface->dev, &dev_attr_brightness);
+	device_remove_file(&interface->dev, &dev_attr_temp);
+	device_remove_file(&interface->dev, &dev_attr_button);
+	device_remove_file(&interface->dev, &dev_attr_port0);
+	device_remove_file(&interface->dev, &dev_attr_port1);
+	usb_set_intfdata (interface, NULL);
+	usb_put_dev(dev->udev);
 	kfree(dev);
+error_mem:
 	return retval;
 }
 
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
new file mode 100644
index 0000000..b88a094
--- /dev/null
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -0,0 +1,2809 @@
+/*
+* USB FTDI client driver for Elan Digital Systems's Uxxx adapters
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+* http://www.elandigitalsystems.com
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+* tony.olech@elandigitalsystems.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, version 2.
+*
+*
+* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB client drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+*/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+MODULE_AUTHOR("Tony Olech");
+MODULE_DESCRIPTION("FTDI ELAN driver");
+MODULE_LICENSE("GPL");
+#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+extern struct platform_driver u132_platform_driver;
+static struct workqueue_struct *status_queue;
+static struct workqueue_struct *command_queue;
+static struct workqueue_struct *respond_queue;
+/*
+* ftdi_module_lock exists to protect access to global variables
+*
+*/
+static struct semaphore ftdi_module_lock;
+static int ftdi_instances = 0;
+static struct list_head ftdi_static_list;
+/*
+* end of the global variables protected by ftdi_module_lock
+*/
+#include "usb_u132.h"
+#define TD_DEVNOTRESP 5
+/* Define these values to match your devices*/
+#define USB_FTDI_ELAN_VENDOR_ID 0x0403
+#define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
+/* table of devices that work with this driver*/
+static struct usb_device_id ftdi_elan_table[] = {
+        {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)},
+        { /* Terminating entry */ }
+};
+
+MODULE_DEVICE_TABLE(usb, ftdi_elan_table);
+/* only the jtag(firmware upgrade device) interface requires
+* a device file and corresponding minor number, but the
+* interface is created unconditionally - I suppose it could
+* be configured or not according to a module parameter.
+* But since we(now) require one interface per device,
+* and since it unlikely that a normal installation would
+* require more than a couple of elan-ftdi devices, 8 seems
+* like a reasonable limit to have here, and if someone
+* really requires more than 8 devices, then they can frig the
+* code and recompile
+*/
+#define USB_FTDI_ELAN_MINOR_BASE 192
+#define COMMAND_BITS 5
+#define COMMAND_SIZE (1<<COMMAND_BITS)
+#define COMMAND_MASK (COMMAND_SIZE-1)
+struct u132_command {
+        u8 header;
+        u16 length;
+        u8 address;
+        u8 width;
+        u32 value;
+        int follows;
+        void *buffer;
+};
+#define RESPOND_BITS 5
+#define RESPOND_SIZE (1<<RESPOND_BITS)
+#define RESPOND_MASK (RESPOND_SIZE-1)
+struct u132_respond {
+        u8 header;
+        u8 address;
+        u32 *value;
+        int *result;
+        struct completion wait_completion;
+};
+struct u132_target {
+        void *endp;
+        struct urb *urb;
+        int toggle_bits;
+        int error_count;
+        int condition_code;
+        int repeat_number;
+        int halted;
+        int skipped;
+        int actual;
+        int non_null;
+        int active;
+        int abandoning;
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+                int toggle_bits, int error_count, int condition_code,
+                int repeat_number, int halted, int skipped, int actual,
+                int non_null);
+};
+/* Structure to hold all of our device specific stuff*/
+struct usb_ftdi {
+        struct list_head ftdi_list;
+        struct semaphore u132_lock;
+        int command_next;
+        int command_head;
+        struct u132_command command[COMMAND_SIZE];
+        int respond_next;
+        int respond_head;
+        struct u132_respond respond[RESPOND_SIZE];
+        struct u132_target target[4];
+        char device_name[16];
+        unsigned synchronized:1;
+        unsigned enumerated:1;
+        unsigned registered:1;
+        unsigned initialized:1;
+        unsigned card_ejected:1;
+        int function;
+        int sequence_num;
+        int disconnected;
+        int gone_away;
+        int stuck_status;
+        int status_queue_delay;
+        struct semaphore sw_lock;
+        struct usb_device *udev;
+        struct usb_interface *interface;
+        struct usb_class_driver *class;
+        struct work_struct status_work;
+        struct work_struct command_work;
+        struct work_struct respond_work;
+        struct u132_platform_data platform_data;
+        struct resource resources[0];
+        struct platform_device platform_dev;
+        unsigned char *bulk_in_buffer;
+        size_t bulk_in_size;
+        size_t bulk_in_last;
+        size_t bulk_in_left;
+        __u8 bulk_in_endpointAddr;
+        __u8 bulk_out_endpointAddr;
+        struct kref kref;
+        u32 controlreg;
+        u8 response[4 + 1024];
+        int expected;
+        int recieved;
+        int ed_found;
+};
+#define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref)
+#define platform_device_to_usb_ftdi(d) container_of(d, struct usb_ftdi, \
+        platform_dev)
+static struct usb_driver ftdi_elan_driver;
+static void ftdi_elan_delete(struct kref *kref)
+{
+        struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref);
+        dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi);
+        usb_put_dev(ftdi->udev);
+        ftdi->disconnected += 1;
+        down(&ftdi_module_lock);
+        list_del_init(&ftdi->ftdi_list);
+        ftdi_instances -= 1;
+        up(&ftdi_module_lock);
+        kfree(ftdi->bulk_in_buffer);
+        ftdi->bulk_in_buffer = NULL;
+}
+
+static void ftdi_elan_put_kref(struct usb_ftdi *ftdi)
+{
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_elan_get_kref(struct usb_ftdi *ftdi)
+{
+        kref_get(&ftdi->kref);
+}
+
+static void ftdi_elan_init_kref(struct usb_ftdi *ftdi)
+{
+        kref_init(&ftdi->kref);
+}
+
+static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+                        return;
+        } else if (queue_work(status_queue, &ftdi->status_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(status_queue, &ftdi->status_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->status_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(command_queue, &ftdi->command_work,
+                        delta))
+                        return;
+        } else if (queue_work(command_queue, &ftdi->command_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(command_queue, &ftdi->command_work,
+                        delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(command_queue, &ftdi->command_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->command_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_response_requeue_work(struct usb_ftdi *ftdi,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(respond_queue, &ftdi->respond_work,
+                        delta))
+                        return;
+        } else if (queue_work(respond_queue, &ftdi->respond_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(respond_queue, &ftdi->respond_work,
+                        delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(respond_queue, &ftdi->respond_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_response_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->respond_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+void ftdi_elan_gone_away(struct platform_device *pdev)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        ftdi->gone_away += 1;
+        ftdi_elan_put_kref(ftdi);
+}
+
+
+EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
+void ftdi_release_platform_dev(struct device *dev)
+{
+        dev->parent = NULL;
+}
+
+static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
+        struct u132_target *target, u8 *buffer, int length);
+static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi);
+static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi);
+static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_synchronize(struct usb_ftdi *ftdi);
+static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi);
+static int ftdi_elan_command_engine(struct usb_ftdi *ftdi);
+static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi);
+static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi)
+{
+        int result;
+        if (ftdi->platform_dev.dev.parent)
+                return -EBUSY;
+        ftdi_elan_get_kref(ftdi);
+        ftdi->platform_data.potpg = 100;
+        ftdi->platform_data.reset = NULL;
+        ftdi->platform_dev.id = ftdi->sequence_num;
+        ftdi->platform_dev.resource = ftdi->resources;
+        ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources);
+        ftdi->platform_dev.dev.platform_data = &ftdi->platform_data;
+        ftdi->platform_dev.dev.parent = NULL;
+        ftdi->platform_dev.dev.release = ftdi_release_platform_dev;
+        ftdi->platform_dev.dev.dma_mask = NULL;
+        snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd");
+        ftdi->platform_dev.name = ftdi->device_name;
+        dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd");
+        request_module("u132_hcd");
+        dev_info(&ftdi->udev->dev, "registering '%s'\n",
+                ftdi->platform_dev.name);
+        result = platform_device_register(&ftdi->platform_dev);
+        return result;
+}
+
+static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi)
+{
+        down(&ftdi->u132_lock);
+        while (ftdi->respond_next > ftdi->respond_head) {
+                struct u132_respond *respond = &ftdi->respond[RESPOND_MASK &
+                        ftdi->respond_head++];
+                *respond->result = -ESHUTDOWN;
+                *respond->value = 0;
+                complete(&respond->wait_completion);
+        } up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                if (target->active == 1) {
+                        target->condition_code = TD_DEVNOTRESP;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, NULL, 0);
+                        down(&ftdi->u132_lock);
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                target->abandoning = 1;
+              wait_1:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x80 | (ed_number << 5) | 0x4;
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait_1;
+                        }
+                }
+              wait_2:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x90 | (ed_number << 5);
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait_2;
+                        }
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                target->abandoning = 1;
+              wait:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x80 | (ed_number << 5) | 0x4;
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait;
+                        }
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
+{
+        ftdi_command_queue_work(ftdi, 0);
+        return;
+}
+
+static void ftdi_elan_command_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                int retval = ftdi_elan_command_engine(ftdi);
+                if (retval == -ESHUTDOWN) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -ENODEV) {
+                        ftdi->disconnected += 1;
+                } else if (retval)
+                        dev_err(&ftdi->udev->dev, "command error %d\n", retval);
+                ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10));
+                return;
+        }
+}
+
+static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi)
+{
+        ftdi_respond_queue_work(ftdi, 0);
+        return;
+}
+
+static void ftdi_elan_respond_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                int retval = ftdi_elan_respond_engine(ftdi);
+                if (retval == 0) {
+                } else if (retval == -ESHUTDOWN) {
+                        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 {
+                        ftdi->disconnected += 1;
+                        dev_err(&ftdi->udev->dev, "respond error %d\n", retval);
+                }
+                if (ftdi->disconnected > 0) {
+                        ftdi_elan_abandon_completions(ftdi);
+                        ftdi_elan_abandon_targets(ftdi);
+                }
+                ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10));
+                return;
+        }
+}
+
+
+/*
+* the sw_lock is initially held and will be freed
+* after the FTDI has been synchronized
+*
+*/
+static void ftdi_elan_status_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        int work_delay_in_msec = 0;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else if (ftdi->synchronized == 0) {
+                down(&ftdi->sw_lock);
+                if (ftdi_elan_synchronize(ftdi) == 0) {
+                        ftdi->synchronized = 1;
+                        ftdi_command_queue_work(ftdi, 1);
+                        ftdi_respond_queue_work(ftdi, 1);
+                        up(&ftdi->sw_lock);
+                        work_delay_in_msec = 100;
+                } else {
+                        dev_err(&ftdi->udev->dev, "synchronize failed\n");
+                        up(&ftdi->sw_lock);
+                        work_delay_in_msec = 10 *1000;
+                }
+        } else if (ftdi->stuck_status > 0) {
+                if (ftdi_elan_stuck_waiting(ftdi) == 0) {
+                        ftdi->stuck_status = 0;
+                        ftdi->synchronized = 0;
+                } else if ((ftdi->stuck_status++ % 60) == 1) {
+                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "
+                                "- please remove\n");
+                } else
+                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "
+                                "- checked %d times\n", ftdi->stuck_status);
+                work_delay_in_msec = 100;
+        } else if (ftdi->enumerated == 0) {
+                if (ftdi_elan_enumeratePCI(ftdi) == 0) {
+                        ftdi->enumerated = 1;
+                        work_delay_in_msec = 250;
+                } else
+                        work_delay_in_msec = 1000;
+        } else if (ftdi->initialized == 0) {
+                if (ftdi_elan_setupOHCI(ftdi) == 0) {
+                        ftdi->initialized = 1;
+                        work_delay_in_msec = 500;
+                } else {
+                        dev_err(&ftdi->udev->dev, "initialized failed - trying "
+                                "again in 10 seconds\n");
+                        work_delay_in_msec = 10 *1000;
+                }
+        } else if (ftdi->registered == 0) {
+                work_delay_in_msec = 10;
+                if (ftdi_elan_hcd_init(ftdi) == 0) {
+                        ftdi->registered = 1;
+                } else
+                        dev_err(&ftdi->udev->dev, "register failed\n");
+                work_delay_in_msec = 250;
+        } else {
+                if (ftdi_elan_checkingPCI(ftdi) == 0) {
+                        work_delay_in_msec = 250;
+                } else if (ftdi->controlreg & 0x00400000) {
+                        if (ftdi->gone_away > 0) {
+                                dev_err(&ftdi->udev->dev, "PCI device eject con"
+                                        "firmed platform_dev.dev.parent=%p plat"
+                                        "form_dev.dev=%p\n",
+                                        ftdi->platform_dev.dev.parent,
+                                        &ftdi->platform_dev.dev);
+                                platform_device_unregister(&ftdi->platform_dev);
+                                ftdi->platform_dev.dev.parent = NULL;
+                                ftdi->registered = 0;
+                                ftdi->enumerated = 0;
+                                ftdi->card_ejected = 0;
+                                ftdi->initialized = 0;
+                                ftdi->gone_away = 0;
+                        } else
+                                ftdi_elan_flush_targets(ftdi);
+                        work_delay_in_msec = 250;
+                } else {
+                        dev_err(&ftdi->udev->dev, "PCI device has disappeared\n"
+                                );
+                        ftdi_elan_cancel_targets(ftdi);
+                        work_delay_in_msec = 500;
+                        ftdi->enumerated = 0;
+                        ftdi->initialized = 0;
+                }
+        }
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                ftdi_status_requeue_work(ftdi,
+                        msecs_to_jiffies(work_delay_in_msec));
+                return;
+        }
+}
+
+
+/*
+* file_operations for the jtag interface
+*
+* the usage count for the device is incremented on open()
+* and decremented on release()
+*/
+static int ftdi_elan_open(struct inode *inode, struct file *file)
+{
+        int subminor = iminor(inode);
+        struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver,
+                subminor);
+        if (!interface) {
+                printk(KERN_ERR "can't find device for minor %d\n", subminor);
+                return -ENODEV;
+        } else {
+                struct usb_ftdi *ftdi = usb_get_intfdata(interface);
+                if (!ftdi) {
+                        return -ENODEV;
+                } else {
+                        if (down_interruptible(&ftdi->sw_lock)) {
+                                return -EINTR;
+                        } else {
+                                ftdi_elan_get_kref(ftdi);
+                                file->private_data = ftdi;
+                                return 0;
+                        }
+                }
+        }
+}
+
+static int ftdi_elan_release(struct inode *inode, struct file *file)
+{
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi == NULL)
+                return -ENODEV;
+        up(&ftdi->sw_lock);        /* decrement the count on our device */
+        ftdi_elan_put_kref(ftdi);
+        return 0;
+}
+
+
+#define FTDI_ELAN_IOC_MAGIC 0xA1
+#define FTDI_ELAN_IOCDEBUG _IOC(_IOC_WRITE, FTDI_ELAN_IOC_MAGIC, 1, 132)
+static int ftdi_elan_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+        switch (cmd) {
+        case FTDI_ELAN_IOCDEBUG:{
+                        char line[132];
+                        int size = strncpy_from_user(line,
+                                (const char __user *)arg, sizeof(line));
+                        if (size < 0) {
+                                return -EINVAL;
+                        } else {
+                                printk(KERN_ERR "TODO: ioctl %s\n", line);
+                                return 0;
+                        }
+                }
+        default:
+                return -EFAULT;
+        }
+}
+
+
+/*
+*
+* blocking bulk reads are used to get data from the device
+*
+*/
+static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
+			      size_t count, loff_t *ppos)
+{
+        char data[30 *3 + 4];
+        char *d = data;
+        int m = (sizeof(data) - 1) / 3;
+        int bytes_read = 0;
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        }
+        data[0] = 0;
+      have:if (ftdi->bulk_in_left > 0) {
+                if (count-- > 0) {
+                        char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer;
+                        ftdi->bulk_in_left -= 1;
+                        if (bytes_read < m) {
+                                d += sprintf(d, " %02X", 0x000000FF & *p);
+                        } else if (bytes_read > m) {
+                        } else
+                                d += sprintf(d, " ..");
+                        if (copy_to_user(buffer++, p, 1)) {
+                                return -EFAULT;
+                        } else {
+                                bytes_read += 1;
+                                goto have;
+                        }
+                } else
+                        return bytes_read;
+        }
+      more:if (count > 0) {
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(50));
+                if (packet_bytes > 2) {
+                        ftdi->bulk_in_left = packet_bytes - 2;
+                        ftdi->bulk_in_last = 1;
+                        goto have;
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else if (bytes_read > 0) {
+                                return bytes_read;
+                        } else
+                                return retval;
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return bytes_read;
+                } else
+                        return retval;
+        } else
+                return bytes_read;
+}
+
+static void ftdi_elan_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
+        if (urb->status && !(urb->status == -ENOENT || urb->status ==
+                -ECONNRESET || urb->status == -ESHUTDOWN)) {
+                dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %"
+                        "d\n", urb, urb->status);
+        }
+        usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+                urb->transfer_buffer, urb->transfer_dma);
+}
+
+static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi,
+        char *buf, int command_size, int total_size)
+{
+        int ed_commands = 0;
+        int b = 0;
+        int I = command_size;
+        int i = ftdi->command_head;
+        while (I-- > 0) {
+                struct u132_command *command = &ftdi->command[COMMAND_MASK &
+                        i++];
+                int F = command->follows;
+                u8 *f = command->buffer;
+                if (command->header & 0x80) {
+                        ed_commands |= 1 << (0x3 & (command->header >> 5));
+                }
+                buf[b++] = command->header;
+                buf[b++] = (command->length >> 0) & 0x00FF;
+                buf[b++] = (command->length >> 8) & 0x00FF;
+                buf[b++] = command->address;
+                buf[b++] = command->width;
+                while (F-- > 0) {
+                        buf[b++] = *f++;
+                }
+        }
+        return ed_commands;
+}
+
+static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size)
+{
+        int total_size = 0;
+        int I = command_size;
+        int i = ftdi->command_head;
+        while (I-- > 0) {
+                struct u132_command *command = &ftdi->command[COMMAND_MASK &
+                        i++];
+                total_size += 5 + command->follows;
+        } return total_size;
+}
+
+static int ftdi_elan_command_engine(struct usb_ftdi *ftdi)
+{
+        int retval;
+        char *buf;
+        int ed_commands;
+        int total_size;
+        struct urb *urb;
+        int command_size = ftdi->command_next - ftdi->command_head;
+        if (command_size == 0)
+                return 0;
+        total_size = ftdi_elan_total_command_size(ftdi, command_size);
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not get a urb to write %d comm"
+                        "ands totaling %d bytes to the Uxxx\n", command_size,
+                        total_size);
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, total_size, GFP_KERNEL,
+                &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer to write %d c"
+                        "ommands totaling %d bytes to the Uxxx\n", command_size,
+                         total_size);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf,
+                command_size, total_size);
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, total_size,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        if (ed_commands) {
+                char diag[40 *3 + 4];
+                char *d = diag;
+                int m = total_size;
+                u8 *c = buf;
+                int s = (sizeof(diag) - 1) / 3;
+                diag[0] = 0;
+                while (s-- > 0 && m-- > 0) {
+                        if (s > 0 || m == 0) {
+                                d += sprintf(d, " %02X", *c++);
+                        } else
+                                d += sprintf(d, " ..");
+                }
+        }
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write "
+                        "%d commands totaling %d bytes to the Uxxx\n", retval,
+                        urb, command_size, total_size);
+                usb_buffer_free(ftdi->udev, total_size, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return retval;
+        }
+        usb_free_urb(urb);        /* release our reference to this urb,
+                the USB core will eventually free it entirely */
+        ftdi->command_head += command_size;
+        ftdi_elan_kick_respond_queue(ftdi);
+        return 0;
+}
+
+static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
+        struct u132_target *target, u8 *buffer, int length)
+{
+        struct urb *urb = target->urb;
+        int halted = target->halted;
+        int skipped = target->skipped;
+        int actual = target->actual;
+        int non_null = target->non_null;
+        int toggle_bits = target->toggle_bits;
+        int error_count = target->error_count;
+        int condition_code = target->condition_code;
+        int repeat_number = target->repeat_number;
+        void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int,
+                int, int, int, int) = target->callback;
+        target->active -= 1;
+        target->callback = NULL;
+        (*callback) (target->endp, urb, buffer, length, toggle_bits,
+                error_count, condition_code, repeat_number, halted, skipped,
+                actual, non_null);
+}
+
+static char *have_ed_set_response(struct usb_ftdi *ftdi,
+        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
+        char *b)
+{
+        int payload = (ed_length >> 0) & 0x07FF;
+        down(&ftdi->u132_lock);
+        target->actual = 0;
+        target->non_null = (ed_length >> 15) & 0x0001;
+        target->repeat_number = (ed_length >> 11) & 0x000F;
+        if (ed_type == 0x02) {
+                if (payload == 0 || target->abandoning > 0) {
+                        target->abandoning = 0;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        return ftdi->response;
+                } else {
+                        ftdi->expected = 4 + payload;
+                        ftdi->ed_found = 1;
+                        up(&ftdi->u132_lock);
+                        return b;
+                }
+        } else if (ed_type == 0x03) {
+                if (payload == 0 || target->abandoning > 0) {
+                        target->abandoning = 0;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        return ftdi->response;
+                } else {
+                        ftdi->expected = 4 + payload;
+                        ftdi->ed_found = 1;
+                        up(&ftdi->u132_lock);
+                        return b;
+                }
+        } else if (ed_type == 0x01) {
+                target->abandoning = 0;
+                up(&ftdi->u132_lock);
+                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                        payload);
+                ftdi->recieved = 0;
+                ftdi->expected = 4;
+                ftdi->ed_found = 0;
+                return ftdi->response;
+        } else {
+                target->abandoning = 0;
+                up(&ftdi->u132_lock);
+                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                        payload);
+                ftdi->recieved = 0;
+                ftdi->expected = 4;
+                ftdi->ed_found = 0;
+                return ftdi->response;
+        }
+}
+
+static char *have_ed_get_response(struct usb_ftdi *ftdi,
+        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
+        char *b)
+{
+        down(&ftdi->u132_lock);
+        target->condition_code = TD_DEVNOTRESP;
+        target->actual = (ed_length >> 0) & 0x01FF;
+        target->non_null = (ed_length >> 15) & 0x0001;
+        target->repeat_number = (ed_length >> 11) & 0x000F;
+        up(&ftdi->u132_lock);
+        if (target->active)
+                ftdi_elan_do_callback(ftdi, target, NULL, 0);
+        target->abandoning = 0;
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        return ftdi->response;
+}
+
+
+/*
+* The engine tries to empty the FTDI fifo
+*
+* all responses found in the fifo data are dispatched thus
+* the response buffer can only ever hold a maximum sized
+* response from the Uxxx.
+*
+*/
+static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
+{
+        u8 *b = ftdi->response + ftdi->recieved;
+        int bytes_read = 0;
+        int retry_on_empty = 1;
+        int retry_on_timeout = 3;
+        int empty_packets = 0;
+      read:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(500));
+                char diag[30 *3 + 4];
+                char *d = diag;
+                int m = packet_bytes;
+                u8 *c = ftdi->bulk_in_buffer;
+                int s = (sizeof(diag) - 1) / 3;
+                diag[0] = 0;
+                while (s-- > 0 && m-- > 0) {
+                        if (s > 0 || m == 0) {
+                                d += sprintf(d, " %02X", *c++);
+                        } else
+                                d += sprintf(d, " ..");
+                }
+                if (packet_bytes > 2) {
+                        ftdi->bulk_in_left = packet_bytes - 2;
+                        ftdi->bulk_in_last = 1;
+                        goto have;
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT with packe"
+                                        "t_bytes = %d with total %d bytes%s\n",
+                                        packet_bytes, bytes_read, diag);
+                                goto more;
+                        } else if (bytes_read > 0) {
+                                dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n",
+                                        bytes_read, diag);
+                                return -ENOMEM;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT with packe"
+                                        "t_bytes = %d with total %d bytes%s\n",
+                                        packet_bytes, bytes_read, diag);
+                                return -ENOMEM;
+                        }
+                } else if (retval == -EILSEQ) {
+                        dev_err(&ftdi->udev->dev, "error = %d with packet_bytes"
+                                " = %d with total %d bytes%s\n", retval,
+                                packet_bytes, bytes_read, diag);
+                        return retval;
+                } else if (retval) {
+                        dev_err(&ftdi->udev->dev, "error = %d with packet_bytes"
+                                " = %d with total %d bytes%s\n", retval,
+                                packet_bytes, bytes_read, diag);
+                        return retval;
+                } else if (packet_bytes == 2) {
+                        unsigned char s0 = ftdi->bulk_in_buffer[0];
+                        unsigned char s1 = ftdi->bulk_in_buffer[1];
+                        empty_packets += 1;
+                        if (s0 == 0x31 && s1 == 0x60) {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        } else if (s0 == 0x31 && s1 == 0x00) {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        } else {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        }
+                } else if (packet_bytes == 1) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return 0;
+                } else {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return 0;
+                }
+        }
+      more:{
+                goto read;
+        }
+      have:if (ftdi->bulk_in_left > 0) {
+                u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last];
+                bytes_read += 1;
+                ftdi->bulk_in_left -= 1;
+                if (ftdi->recieved == 0 && c == 0xFF) {
+                        goto have;
+                } else
+                        *b++ = c;
+                if (++ftdi->recieved < ftdi->expected) {
+                        goto have;
+                } else if (ftdi->ed_found) {
+                        int ed_number = (ftdi->response[0] >> 5) & 0x03;
+                        u16 ed_length = (ftdi->response[2] << 8) |
+                                ftdi->response[1];
+                        struct u132_target *target = &ftdi->target[ed_number];
+                        int payload = (ed_length >> 0) & 0x07FF;
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = payload;
+                        u8 *c = 4 + ftdi->response;
+                        int s = (sizeof(diag) - 1) / 3;
+                        diag[0] = 0;
+                        while (s-- > 0 && m-- > 0) {
+                                if (s > 0 || m == 0) {
+                                        d += sprintf(d, " %02X", *c++);
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        b = ftdi->response;
+                        goto have;
+                } else if (ftdi->expected == 8) {
+                        u8 buscmd;
+                        int respond_head = ftdi->respond_head++;
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & respond_head];
+                        u32 data = ftdi->response[7];
+                        data <<= 8;
+                        data |= ftdi->response[6];
+                        data <<= 8;
+                        data |= ftdi->response[5];
+                        data <<= 8;
+                        data |= ftdi->response[4];
+                        *respond->value = data;
+                        *respond->result = 0;
+                        complete(&respond->wait_completion);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        b = ftdi->response;
+                        buscmd = (ftdi->response[0] >> 0) & 0x0F;
+                        if (buscmd == 0x00) {
+                        } else if (buscmd == 0x02) {
+                        } else if (buscmd == 0x06) {
+                        } else if (buscmd == 0x0A) {
+                        } else
+                                dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) va"
+                                        "lue = %08X\n", buscmd, data);
+                        goto have;
+                } else {
+                        if ((ftdi->response[0] & 0x80) == 0x00) {
+                                ftdi->expected = 8;
+                                goto have;
+                        } else {
+                                int ed_number = (ftdi->response[0] >> 5) & 0x03;
+                                int ed_type = (ftdi->response[0] >> 0) & 0x03;
+                                u16 ed_length = (ftdi->response[2] << 8) |
+                                        ftdi->response[1];
+                                struct u132_target *target = &ftdi->target[
+                                        ed_number];
+                                target->halted = (ftdi->response[0] >> 3) &
+                                        0x01;
+                                target->skipped = (ftdi->response[0] >> 2) &
+                                        0x01;
+                                target->toggle_bits = (ftdi->response[3] >> 6)
+                                        & 0x03;
+                                target->error_count = (ftdi->response[3] >> 4)
+                                        & 0x03;
+                                target->condition_code = (ftdi->response[
+                                        3] >> 0) & 0x0F;
+                                if ((ftdi->response[0] & 0x10) == 0x00) {
+                                        b = have_ed_set_response(ftdi, target,
+                                                ed_length, ed_number, ed_type,
+                                                b);
+                                        goto have;
+                                } else {
+                                        b = have_ed_get_response(ftdi, target,
+                                                ed_length, ed_number, ed_type,
+                                                b);
+                                        goto have;
+                                }
+                        }
+                }
+        } else
+                goto more;
+}
+
+
+/*
+* create a urb, and a buffer for it, and copy the data to the urb
+*
+*/
+static ssize_t ftdi_elan_write(struct file *file,
+			       const char __user *user_buffer, size_t count,
+			       loff_t *ppos)
+{
+        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;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        }
+        if (count == 0) {
+                goto exit;
+        }
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                retval = -ENOMEM;
+                goto error_1;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, count, GFP_KERNEL,
+                &urb->transfer_dma);
+        if (!buf) {
+                retval = -ENOMEM;
+                goto error_2;
+        }
+        if (copy_from_user(buf, user_buffer, count)) {
+                retval = -EFAULT;
+                goto error_3;
+        }
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, count,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed submitting write urb, error %"
+                        "d\n", retval);
+                goto error_4;
+        }
+        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++);
+                }
+        }
+        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;
+}
+
+static struct file_operations ftdi_elan_fops = {
+        .owner = THIS_MODULE,
+        .llseek = no_llseek,
+        .ioctl = ftdi_elan_ioctl,
+        .read = ftdi_elan_read,
+        .write = ftdi_elan_write,
+        .open = ftdi_elan_open,
+        .release = ftdi_elan_release,
+};
+
+/*
+* usb class driver info in order to get a minor number from the usb core,
+* and to have the device registered with the driver core
+*/
+static struct usb_class_driver ftdi_elan_jtag_class = {
+        .name = "ftdi-%d-jtag",
+        .fops = &ftdi_elan_fops,
+        .minor_base = USB_FTDI_ELAN_MINOR_BASE,
+};
+
+/*
+* the following definitions are for the
+* ELAN FPGA state machgine processor that
+* lies on the other side of the FTDI chip
+*/
+#define cPCIu132rd 0x0
+#define cPCIu132wr 0x1
+#define cPCIiord 0x2
+#define cPCIiowr 0x3
+#define cPCImemrd 0x6
+#define cPCImemwr 0x7
+#define cPCIcfgrd 0xA
+#define cPCIcfgwr 0xB
+#define cPCInull 0xF
+#define cU132cmd_status 0x0
+#define cU132flash 0x1
+#define cPIDsetup 0x0
+#define cPIDout 0x1
+#define cPIDin 0x2
+#define cPIDinonce 0x3
+#define cCCnoerror 0x0
+#define cCCcrc 0x1
+#define cCCbitstuff 0x2
+#define cCCtoggle 0x3
+#define cCCstall 0x4
+#define cCCnoresp 0x5
+#define cCCbadpid1 0x6
+#define cCCbadpid2 0x7
+#define cCCdataoverrun 0x8
+#define cCCdataunderrun 0x9
+#define cCCbuffoverrun 0xC
+#define cCCbuffunderrun 0xD
+#define cCCnotaccessed 0xF
+static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data)
+{
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | cPCIu132wr;
+                        command->length = 0x04;
+                        command->address = 0x00;
+                        command->width = 0x00;
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset,
+        u8 width, u32 data)
+{
+        u8 addressofs = config_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | (cPCIcfgwr & 0x0F);
+                        command->length = 0x04;
+                        command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset,
+        u8 width, u32 data)
+{
+        u8 addressofs = mem_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | (cPCImemwr & 0x0F);
+                        command->length = 0x04;
+                        command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
+        u8 width, u32 data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_write_pcimem);
+static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
+{
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | cPCIu132rd;
+                        command->length = 0x04;
+                        respond->address = command->address = cU132cmd_status;
+                        command->width = 0x00;
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_read_reg(ftdi, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg);
+static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
+        u8 width, u32 *data)
+{
+        u8 addressofs = config_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | (cPCIcfgrd &
+                                0x0F);
+                        command->length = 0x04;
+                        respond->address = command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset,
+        u8 width, u32 *data)
+{
+        u8 addressofs = mem_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | (cPCImemrd &
+                                0x0F);
+                        command->length = 0x04;
+                        respond->address = command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
+        u8 width, u32 *data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else
+                return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_pcimem);
+static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x80 | (ed << 5);
+                        command->length = 0x8007;
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 8;
+                        command->value = 0;
+                        command->buffer = urb->setup_packet;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_setup);
+static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        int remaining_length = urb->transfer_buffer_length -
+                                urb->actual_length;
+                        command->header = 0x82 | (ed << 5);
+                        if (remaining_length == 0) {
+                                command->length = 0x0000;
+                        } else if (remaining_length > 1024) {
+                                command->length = 0x8000 | 1023;
+                        } else
+                                command->length = 0x8000 | (remaining_length -
+                                        1);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_input);
+static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x81 | (ed << 5);
+                        command->length = 0x0000;
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_empty);
+static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        u8 *b;
+                        u16 urb_size;
+                        int i = 0;
+                        char data[30 *3 + 4];
+                        char *d = data;
+                        int m = (sizeof(data) - 1) / 3;
+                        int l = 0;
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x81 | (ed << 5);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = min(1024,
+                                urb->transfer_buffer_length -
+                                urb->actual_length);
+                        command->value = 0;
+                        command->buffer = urb->transfer_buffer +
+                                urb->actual_length;
+                        command->length = 0x8000 | (command->follows - 1);
+                        b = command->buffer;
+                        urb_size = command->follows;
+                        data[0] = 0;
+                        while (urb_size-- > 0) {
+                                if (i > m) {
+                                } else if (i++ < m) {
+                                        int w = sprintf(d, " %02X", *b++);
+                                        d += w;
+                                        l += w;
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_output);
+static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        int remaining_length = urb->transfer_buffer_length -
+                                urb->actual_length;
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x83 | (ed << 5);
+                        if (remaining_length == 0) {
+                                command->length = 0x0000;
+                        } else if (remaining_length > 1024) {
+                                command->length = 0x8000 | 1023;
+                        } else
+                                command->length = 0x8000 | (remaining_length -
+                                        1);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_single);
+static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp)
+{
+        u8 ed = ed_number - 1;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                struct u132_target *target = &ftdi->target[ed];
+                down(&ftdi->u132_lock);
+                if (target->abandoning > 0) {
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        target->abandoning = 1;
+                      wait_1:if (target->active == 1) {
+                                int command_size = ftdi->command_next -
+                                        ftdi->command_head;
+                                if (command_size < COMMAND_SIZE) {
+                                        struct u132_command *command =
+                                                &ftdi->command[COMMAND_MASK &
+                                                ftdi->command_next];
+                                        command->header = 0x80 | (ed << 5) |
+                                                0x4;
+                                        command->length = 0x00;
+                                        command->address = 0x00;
+                                        command->width = 0x00;
+                                        command->follows = 0;
+                                        command->value = 0;
+                                        command->buffer = &command->value;
+                                        ftdi->command_next += 1;
+                                        ftdi_elan_kick_command_queue(ftdi);
+                                } else {
+                                        up(&ftdi->u132_lock);
+                                        msleep(100);
+                                        down(&ftdi->u132_lock);
+                                        goto wait_1;
+                                }
+                        }
+                        up(&ftdi->u132_lock);
+                        return 0;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
+        void *endp)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_flush(ftdi, ed_number, endp);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_flush);
+static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi)
+{
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        int retry_on_status = 20;
+      more:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(100));
+                if (packet_bytes > 2) {
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = (sizeof(diag) - 1) / 3;
+                        char *b = ftdi->bulk_in_buffer;
+                        int bytes_read = 0;
+                        diag[0] = 0;
+                        while (packet_bytes-- > 0) {
+                                char c = *b++;
+                                if (bytes_read < m) {
+                                        d += sprintf(d, " %02X",
+                                                0x000000FF & c);
+                                } else if (bytes_read > m) {
+                                } else
+                                        d += sprintf(d, " ..");
+                                bytes_read += 1;
+                                continue;
+                        }
+                        goto more;
+                } else if (packet_bytes > 1) {
+                        char s1 = ftdi->bulk_in_buffer[0];
+                        char s2 = ftdi->bulk_in_buffer[1];
+                        if (s1 == 0x31 && s2 == 0x60) {
+                                return 0;
+                        } else if (retry_on_status-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (packet_bytes > 0) {
+                        char b1 = ftdi->bulk_in_buffer[0];
+                        dev_err(&ftdi->udev->dev, "only one byte flushed from F"
+                                "TDI = %02X\n", b1);
+                        if (retry_on_status-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT retry limi"
+                                        "t reached\n");
+                                return -ENOMEM;
+                        }
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "empty packet retry l"
+                                        "imit reached\n");
+                                return -ENOMEM;
+                        }
+                } else {
+                        dev_err(&ftdi->udev->dev, "error = %d\n", retval);
+                        return retval;
+                }
+        }
+        return -1;
+}
+
+
+/*
+* send the long flush sequence
+*
+*/
+static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi)
+{
+        int retval;
+        struct urb *urb;
+        char *buf;
+        int I = 257;
+        int i = 0;
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not alloc a urb for flush sequ"
+                        "ence\n");
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer for flush seq"
+                        "uence\n");
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        while (I-- > 0)
+                buf[i++] = 0x55;
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, i,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed to submit urb containing the "
+                        "flush sequence\n");
+                usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        usb_free_urb(urb);
+        return 0;
+}
+
+
+/*
+* send the reset sequence
+*
+*/
+static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi)
+{
+        int retval;
+        struct urb *urb;
+        char *buf;
+        int I = 4;
+        int i = 0;
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not get a urb for the reset se"
+                        "quence\n");
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer for the reset"
+                        " sequence\n");
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        buf[i++] = 0x55;
+        buf[i++] = 0xAA;
+        buf[i++] = 0x5A;
+        buf[i++] = 0xA5;
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, i,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed to submit urb containing the "
+                        "reset sequence\n");
+                usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        usb_free_urb(urb);
+        return 0;
+}
+
+static int ftdi_elan_synchronize(struct usb_ftdi *ftdi)
+{
+        int retval;
+        int long_stop = 10;
+        int retry_on_timeout = 5;
+        int retry_on_empty = 10;
+        int err_count = 0;
+        retval = ftdi_elan_flush_input_fifo(ftdi);
+        if (retval)
+                return retval;
+        ftdi->bulk_in_left = 0;
+        ftdi->bulk_in_last = -1;
+        while (long_stop-- > 0) {
+                int read_stop;
+                int read_stuck;
+                retval = ftdi_elan_synchronize_flush(ftdi);
+                if (retval)
+                        return retval;
+                retval = ftdi_elan_flush_input_fifo(ftdi);
+                if (retval)
+                        return retval;
+              reset:retval = ftdi_elan_synchronize_reset(ftdi);
+                if (retval)
+                        return retval;
+                read_stop = 100;
+                read_stuck = 10;
+              read:{
+                        int packet_bytes = 0;
+                        retval = usb_bulk_msg(ftdi->udev,
+                                usb_rcvbulkpipe(ftdi->udev,
+                                ftdi->bulk_in_endpointAddr),
+                                ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                                &packet_bytes, msecs_to_jiffies(500));
+                        if (packet_bytes > 2) {
+                                char diag[30 *3 + 4];
+                                char *d = diag;
+                                int m = (sizeof(diag) - 1) / 3;
+                                char *b = ftdi->bulk_in_buffer;
+                                int bytes_read = 0;
+                                unsigned char c = 0;
+                                diag[0] = 0;
+                                while (packet_bytes-- > 0) {
+                                        c = *b++;
+                                        if (bytes_read < m) {
+                                                d += sprintf(d, " %02X", c);
+                                        } else if (bytes_read > m) {
+                                        } else
+                                                d += sprintf(d, " ..");
+                                        bytes_read += 1;
+                                        continue;
+                                }
+                                if (c == 0x7E) {
+                                        return 0;
+                                } else {
+                                        if (c == 0x55) {
+                                                goto read;
+                                        } else if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                }
+                        } else if (packet_bytes > 1) {
+                                unsigned char s1 = ftdi->bulk_in_buffer[0];
+                                unsigned char s2 = ftdi->bulk_in_buffer[1];
+                                if (s1 == 0x31 && s2 == 0x00) {
+                                        if (read_stuck-- > 0) {
+                                                goto read;
+                                        } else
+                                                goto reset;
+                                } else if (s1 == 0x31 && s2 == 0x60) {
+                                        if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                } else {
+                                        if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                }
+                        } else if (packet_bytes > 0) {
+                                if (read_stop-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "retry limit "
+                                                "reached\n");
+                                        continue;
+                                }
+                        } else if (retval == -ETIMEDOUT) {
+                                if (retry_on_timeout-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "TIMED OUT re"
+                                                "try limit reached\n");
+                                        continue;
+                                }
+                        } else if (retval == 0) {
+                                if (retry_on_empty-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "empty packet"
+                                                " retry limit reached\n");
+                                        continue;
+                                }
+                        } else {
+                                err_count += 1;
+                                dev_err(&ftdi->udev->dev, "error = %d\n",
+                                        retval);
+                                if (read_stop-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "retry limit "
+                                                "reached\n");
+                                        continue;
+                                }
+                        }
+                }
+        }
+        dev_err(&ftdi->udev->dev, "failed to synchronize\n");
+        return -EFAULT;
+}
+
+static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi)
+{
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        int retry_on_status = 50;
+      more:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(1000));
+                if (packet_bytes > 2) {
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = (sizeof(diag) - 1) / 3;
+                        char *b = ftdi->bulk_in_buffer;
+                        int bytes_read = 0;
+                        diag[0] = 0;
+                        while (packet_bytes-- > 0) {
+                                char c = *b++;
+                                if (bytes_read < m) {
+                                        d += sprintf(d, " %02X",
+                                                0x000000FF & c);
+                                } else if (bytes_read > m) {
+                                } else
+                                        d += sprintf(d, " ..");
+                                bytes_read += 1;
+                                continue;
+                        }
+                        goto more;
+                } else if (packet_bytes > 1) {
+                        char s1 = ftdi->bulk_in_buffer[0];
+                        char s2 = ftdi->bulk_in_buffer[1];
+                        if (s1 == 0x31 && s2 == 0x60) {
+                                return 0;
+                        } else if (retry_on_status-- > 0) {
+                                msleep(5);
+                                goto more;
+                        } else
+                                return -EFAULT;
+                } else if (packet_bytes > 0) {
+                        char b1 = ftdi->bulk_in_buffer[0];
+                        dev_err(&ftdi->udev->dev, "only one byte flushed from F"
+                                "TDI = %02X\n", b1);
+                        if (retry_on_status-- > 0) {
+                                msleep(5);
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT retry limi"
+                                        "t reached\n");
+                                return -ENOMEM;
+                        }
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "empty packet retry l"
+                                        "imit reached\n");
+                                return -ENOMEM;
+                        }
+                } else {
+                        dev_err(&ftdi->udev->dev, "error = %d\n", retval);
+                        return -ENOMEM;
+                }
+        }
+        return -1;
+}
+
+static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
+{
+        int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        if (ftdi->controlreg & 0x00400000) {
+                if (ftdi->card_ejected) {
+                } else {
+                        ftdi->card_ejected = 1;
+                        dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = "
+                                "%08X\n", ftdi->controlreg);
+                }
+                return -ENODEV;
+        } else {
+                u8 fn = ftdi->function - 1;
+                int activePCIfn = fn << 8;
+                u32 pcidata;
+                u32 pciVID;
+                u32 pciPID;
+                int reg = 0;
+                UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                        &pcidata);
+                if (UxxxStatus)
+                        return UxxxStatus;
+                pciVID = pcidata & 0xFFFF;
+                pciPID = (pcidata >> 16) & 0xFFFF;
+                if (pciVID == ftdi->platform_data.vendor && pciPID ==
+                        ftdi->platform_data.device) {
+                        return 0;
+                } else {
+                        dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X devi"
+                                "ce=%04X pciPID=%04X\n",
+                                ftdi->platform_data.vendor, pciVID,
+                                ftdi->platform_data.device, pciPID);
+                        return -ENODEV;
+                }
+        }
+}
+
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
+{
+        u32 latence_timer;
+        u32 controlreg;
+        int UxxxStatus;
+        u32 pcidata;
+        int reg = 0;
+        int foundOHCI = 0;
+        u8 fn;
+        int activePCIfn = 0;
+        u32 pciVID = 0;
+        u32 pciPID = 0;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(750);
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(250);
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(1000);
+        for (fn = 0; (fn < 4) && (!foundOHCI); fn++) {
+                activePCIfn = fn << 8;
+                ftdi->function = fn + 1;
+                UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                        &pcidata);
+                if (UxxxStatus)
+                        return UxxxStatus;
+                pciVID = pcidata & 0xFFFF;
+                pciPID = (pcidata >> 16) & 0xFFFF;
+                if ((pciVID == 0x1045) && (pciPID == 0xc861)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x1033) && (pciPID == 0x0035)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) {
+                }
+        }
+        if (foundOHCI == 0) {
+                return -ENXIO;
+        }
+        ftdi->platform_data.vendor = pciVID;
+        ftdi->platform_data.device = pciPID;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 16;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+                0xFFFFFFFF);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+                0xF0000000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 12;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &latence_timer);
+        if (UxxxStatus)
+                return UxxxStatus;
+        latence_timer &= 0xFFFF00FF;
+        latence_timer |= 0x00001600;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+                latence_timer);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 4;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+                0x06);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        return 0;
+}
+
+static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
+{
+        u32 pcidata;
+        int U132Status;
+        int reg;
+        int reset_repeat = 0;
+      do_reset:reg = 8;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01);
+        if (U132Status)
+                return U132Status;
+      reset_check:{
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+                if (pcidata & 1) {
+                        msleep(500);
+                        if (reset_repeat++ > 100) {
+                                reset_repeat = 0;
+                                goto do_reset;
+                        } else
+                                goto reset_check;
+                }
+        }
+        goto dump_regs;
+        msleep(500);
+        reg = 0x28;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x40;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x34;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 4;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(250);
+        reg = 8;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x28;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 8;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x48;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x34;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(100);
+        reg = 0x50;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+      power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        if (!(pcidata & 1)) {
+                msleep(500);
+                goto power_check;
+        }
+        msleep(3000);
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(750);
+        reg = 0x54;
+        if (0) {
+                U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
+                if (U132Status)
+                        return U132Status;
+        }
+        if (0) {
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+        }
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+      dump_regs:for (reg = 0; reg <= 0x54; reg += 4) {
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+        }
+        return 0;
+}
+
+
+/*
+* we use only the first bulk-in and bulk-out endpoints
+*/
+static int ftdi_elan_probe(struct usb_interface *interface,
+        const struct usb_device_id *id)
+{
+        struct usb_host_interface *iface_desc;
+        struct usb_endpoint_descriptor *endpoint;
+        size_t buffer_size;
+        int i;
+        int retval = -ENOMEM;
+        struct usb_ftdi *ftdi = kmalloc(sizeof(struct usb_ftdi), GFP_KERNEL);
+        if (ftdi == NULL) {
+                printk(KERN_ERR "Out of memory\n");
+                return -ENOMEM;
+        }
+        memset(ftdi, 0x00, sizeof(struct usb_ftdi));
+        down(&ftdi_module_lock);
+        list_add_tail(&ftdi->ftdi_list, &ftdi_static_list);
+        ftdi->sequence_num = ++ftdi_instances;
+        up(&ftdi_module_lock);
+        ftdi_elan_init_kref(ftdi);
+        init_MUTEX(&ftdi->sw_lock);
+        ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
+        ftdi->interface = interface;
+        init_MUTEX(&ftdi->u132_lock);
+        ftdi->expected = 4;
+        iface_desc = interface->cur_altsetting;
+        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+                endpoint = &iface_desc->endpoint[i].desc;
+                if (!ftdi->bulk_in_endpointAddr &&
+                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                        == USB_DIR_IN) && ((endpoint->bmAttributes &
+                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
+                        {
+                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                        ftdi->bulk_in_size = buffer_size;
+                        ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+                        ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+                        if (!ftdi->bulk_in_buffer) {
+                                dev_err(&ftdi->udev->dev, "Could not allocate b"
+                                        "ulk_in_buffer\n");
+                                retval = -ENOMEM;
+                                goto error;
+                        }
+                }
+                if (!ftdi->bulk_out_endpointAddr &&
+                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                        == USB_DIR_OUT) && ((endpoint->bmAttributes &
+                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
+                        {
+                        ftdi->bulk_out_endpointAddr =
+                                endpoint->bEndpointAddress;
+                }
+        }
+        if (!(ftdi->bulk_in_endpointAddr && ftdi->bulk_out_endpointAddr)) {
+                dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk"
+                        "-out endpoints\n");
+                retval = -ENODEV;
+                goto error;
+        }
+        dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n",
+                iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr,
+                ftdi->bulk_out_endpointAddr);
+        usb_set_intfdata(interface, ftdi);
+        if (iface_desc->desc.bInterfaceNumber == 0 &&
+                ftdi->bulk_in_endpointAddr == 0x81 &&
+                ftdi->bulk_out_endpointAddr == 0x02) {
+                retval = usb_register_dev(interface, &ftdi_elan_jtag_class);
+                if (retval) {
+                        dev_err(&ftdi->udev->dev, "Not able to get a minor for "
+                                "this device.\n");
+                        usb_set_intfdata(interface, NULL);
+                        retval = -ENOMEM;
+                        goto error;
+                } else {
+                        ftdi->class = &ftdi_elan_jtag_class;
+                        dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface "
+                                "%d now attached to ftdi%d\n", ftdi,
+                                iface_desc->desc.bInterfaceNumber,
+                                interface->minor);
+                        return 0;
+                }
+        } else if (iface_desc->desc.bInterfaceNumber == 1 &&
+                ftdi->bulk_in_endpointAddr == 0x83 &&
+                ftdi->bulk_out_endpointAddr == 0x04) {
+                ftdi->class = NULL;
+                dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a"
+                        "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber);
+                INIT_WORK(&ftdi->status_work, ftdi_elan_status_work,
+                        (void *)ftdi);
+                INIT_WORK(&ftdi->command_work, ftdi_elan_command_work,
+                        (void *)ftdi);
+                INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work,
+                        (void *)ftdi);
+                ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000));
+                return 0;
+        } else {
+                dev_err(&ftdi->udev->dev,
+                        "Could not find ELAN's U132 device\n");
+                retval = -ENODEV;
+                goto error;
+        }
+      error:if (ftdi) {
+                ftdi_elan_put_kref(ftdi);
+        }
+        return retval;
+}
+
+static void ftdi_elan_disconnect(struct usb_interface *interface)
+{
+        struct usb_ftdi *ftdi = usb_get_intfdata(interface);
+        ftdi->disconnected += 1;
+        if (ftdi->class) {
+                int minor = interface->minor;
+                struct usb_class_driver *class = ftdi->class;
+                usb_set_intfdata(interface, NULL);
+                usb_deregister_dev(interface, class);
+                dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on min"
+                        "or %d now disconnected\n", minor);
+        } else {
+                ftdi_status_cancel_work(ftdi);
+                ftdi_command_cancel_work(ftdi);
+                ftdi_response_cancel_work(ftdi);
+                ftdi_elan_abandon_completions(ftdi);
+                ftdi_elan_abandon_targets(ftdi);
+                if (ftdi->registered) {
+                        platform_device_unregister(&ftdi->platform_dev);
+                        ftdi->synchronized = 0;
+                        ftdi->enumerated = 0;
+                        ftdi->registered = 0;
+                }
+                flush_workqueue(status_queue);
+                flush_workqueue(command_queue);
+                flush_workqueue(respond_queue);
+                ftdi->disconnected += 1;
+                usb_set_intfdata(interface, NULL);
+                dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller inter"
+                        "face now disconnected\n");
+        }
+        ftdi_elan_put_kref(ftdi);
+}
+
+static struct usb_driver ftdi_elan_driver = {
+        .name = "ftdi-elan",
+        .probe = ftdi_elan_probe,
+        .disconnect = ftdi_elan_disconnect,
+        .id_table = ftdi_elan_table,
+};
+static int __init ftdi_elan_init(void)
+{
+        int result;
+        printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
+                 __TIME__, __DATE__);
+        init_MUTEX(&ftdi_module_lock);
+        INIT_LIST_HEAD(&ftdi_static_list);
+        status_queue = create_singlethread_workqueue("ftdi-status-control");
+        command_queue = create_singlethread_workqueue("ftdi-command-engine");
+        respond_queue = create_singlethread_workqueue("ftdi-respond-engine");
+        result = usb_register(&ftdi_elan_driver);
+        if (result)
+                printk(KERN_ERR "usb_register failed. Error number %d\n",
+                        result);
+        return result;
+}
+
+static void __exit ftdi_elan_exit(void)
+{
+        struct usb_ftdi *ftdi;
+        struct usb_ftdi *temp;
+        usb_deregister(&ftdi_elan_driver);
+        printk(KERN_INFO "ftdi_u132 driver deregistered\n");
+        list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) {
+                ftdi_status_cancel_work(ftdi);
+                ftdi_command_cancel_work(ftdi);
+                ftdi_response_cancel_work(ftdi);
+        } flush_workqueue(status_queue);
+        destroy_workqueue(status_queue);
+        status_queue = NULL;
+        flush_workqueue(command_queue);
+        destroy_workqueue(command_queue);
+        command_queue = NULL;
+        flush_workqueue(respond_queue);
+        destroy_workqueue(respond_queue);
+        respond_queue = NULL;
+}
+
+
+module_init(ftdi_elan_init);
+module_exit(ftdi_elan_exit);
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index fcd69c5..8e6e195 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -98,7 +98,7 @@
 static void idmouse_disconnect(struct usb_interface *interface);
 
 /* file operation pointers */
-static struct file_operations idmouse_fops = {
+static const struct file_operations idmouse_fops = {
 	.owner = THIS_MODULE,
 	.read = idmouse_read,
 	.open = idmouse_open,
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index f30ab1f..10b6403 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -589,7 +589,7 @@
 }
 
 /* file operations needed when we register this driver */
-static struct file_operations ld_usb_fops = {
+static const struct file_operations ld_usb_fops = {
 	.owner =	THIS_MODULE,
 	.read  =	ld_usb_read,
 	.write =	ld_usb_write,
@@ -657,15 +657,11 @@
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 
-		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+		if (usb_endpoint_is_int_in(endpoint))
 			dev->interrupt_in_endpoint = endpoint;
-		}
 
-		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+		if (usb_endpoint_is_int_out(endpoint))
 			dev->interrupt_out_endpoint = endpoint;
-		}
 	}
 	if (dev->interrupt_in_endpoint == NULL) {
 		dev_err(&intf->dev, "Interrupt in endpoint not found\n");
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 7699d97..77c36e6 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -259,7 +259,7 @@
 static DEFINE_MUTEX (disconnect_mutex);
 
 /* file operations needed when we register this driver */
-static struct file_operations tower_fops = {
+static const struct file_operations tower_fops = {
 	.owner =	THIS_MODULE,
 	.read  =	tower_read,
 	.write =	tower_write,
diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c
new file mode 100644
index 0000000..735ed33
--- /dev/null
+++ b/drivers/usb/misc/phidget.c
@@ -0,0 +1,43 @@
+/*
+ * USB Phidgets class
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/device.h>
+
+struct class *phidget_class;
+
+static int __init init_phidget(void)
+{
+	phidget_class = class_create(THIS_MODULE, "phidget");
+
+	if (IS_ERR(phidget_class))
+		return PTR_ERR(phidget_class);
+
+	return 0;
+}
+
+static void __exit cleanup_phidget(void)
+{
+	class_destroy(phidget_class);
+}
+
+EXPORT_SYMBOL_GPL(phidget_class);
+
+module_init(init_phidget);
+module_exit(cleanup_phidget);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sean Young <sean@mess.org>");
+MODULE_DESCRIPTION("Container module for phidget class");
+
diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h
new file mode 100644
index 0000000..c401190
--- /dev/null
+++ b/drivers/usb/misc/phidget.h
@@ -0,0 +1,12 @@
+/*
+ * USB Phidgets class
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.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.
+ */
+
+extern struct class *phidget_class;
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index bfbbbfb..78e4199 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 
+#include "phidget.h"
+
 #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
 #define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
 
@@ -42,26 +44,35 @@
 	int inputs;
 	int outputs;
 	int has_lcd;
+	int amnesiac;
 };
-#define ifkit(_sensors, _inputs, _outputs, _lcd)			\
-static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = {	\
+
+#define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac)		\
+{									\
 	.sensors	= _sensors,					\
 	.inputs		= _inputs,					\
 	.outputs	= _outputs,					\
 	.has_lcd	= _lcd,						\
+	.amnesiac	= _amnesiac					\
 };
-ifkit(0, 0, 4, 0);
-ifkit(8, 8, 8, 0);
-ifkit(0, 4, 7, 1);
-ifkit(8, 8, 4, 0);
-ifkit(0, 8, 8, 1);
-ifkit(0, 16, 16, 0);
+
+static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0);
+static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1);
+static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0);
+static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0);
+static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0);
+static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0);
+static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0);
+
+static unsigned long device_no;
 
 struct interfacekit {
 	struct usb_device *udev;
 	struct usb_interface *intf;
 	struct driver_interfacekit *ifkit;
+	struct device *dev;
 	unsigned long outputs;
+	int dev_no;
 	u8 inputs[MAX_INTERFACES];
 	u16 sensors[MAX_INTERFACES];
 	u8 lcd_files_on;
@@ -71,6 +82,7 @@
 	dma_addr_t data_dma;
 
 	struct work_struct do_notify;
+	struct work_struct do_resubmit;
 	unsigned long input_events;
 	unsigned long sensor_events;
 };
@@ -78,8 +90,10 @@
 static struct usb_device_id id_table[] = {
 	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004),
 		.driver_info = (kernel_ulong_t)&ph_004},
-	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888),
-		.driver_info = (kernel_ulong_t)&ph_888},
+	{USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814),
+		.driver_info = (kernel_ulong_t)&ph_888o},
+	{USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff),
+		.driver_info = (kernel_ulong_t)&ph_888n},
 	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047),
 		.driver_info = (kernel_ulong_t)&ph_047},
 	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
@@ -92,16 +106,11 @@
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-static int change_outputs(struct interfacekit *kit, int output_num, int enable)
+static int set_outputs(struct interfacekit *kit)
 {
 	u8 *buffer;
 	int retval;
 
-	if (enable)
-		set_bit(output_num, &kit->outputs);
-	else
-		clear_bit(output_num, &kit->outputs);
-
 	buffer = kzalloc(4, GFP_KERNEL);
 	if (!buffer) {
 		dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
@@ -121,6 +130,9 @@
 				retval);
 	kfree(buffer);
 
+	if (kit->ifkit->amnesiac)
+		schedule_delayed_work(&kit->do_resubmit, HZ / 2);
+
 	return retval < 0 ? retval : 0;
 }
 
@@ -180,21 +192,24 @@
 }
 
 #define set_lcd_line(number)	\
-static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
-{											\
-	struct usb_interface *intf = to_usb_interface(dev);				\
-	struct interfacekit *kit = usb_get_intfdata(intf);				\
-	change_string(kit, buf, number - 1);						\
-	return count;									\
-}											\
-static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
+static ssize_t lcd_line_##number(struct device *dev,			\
+					struct device_attribute *attr,	\
+					const char *buf, size_t count)	\
+{									\
+	struct interfacekit *kit = dev_get_drvdata(dev);		\
+	change_string(kit, buf, number - 1);				\
+	return count;							\
+}
+
+#define lcd_line_attr(number)						\
+	__ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number)
+
 set_lcd_line(1);
 set_lcd_line(2);
 
 static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct interfacekit *kit = usb_get_intfdata(intf);
+	struct interfacekit *kit = dev_get_drvdata(dev);
 	int enabled;
 	unsigned char *buffer;
 	int retval = -ENOMEM;
@@ -226,23 +241,30 @@
 	kfree(buffer);
 	return retval;
 }
-static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
+
+static struct device_attribute dev_lcd_line_attrs[] = {
+	lcd_line_attr(1),
+	lcd_line_attr(2),
+	__ATTR(backlight, S_IWUGO, NULL, set_backlight)
+};
 
 static void remove_lcd_files(struct interfacekit *kit)
 {
+	int i;
+
 	if (kit->lcd_files_on) {
 		dev_dbg(&kit->udev->dev, "Removing lcd files\n");
-		device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1);
-		device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2);
-		device_remove_file(&kit->intf->dev, &dev_attr_backlight);
+
+		for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++)
+			device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
 	}
 }
 
 static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct interfacekit *kit = usb_get_intfdata(intf);
+	struct interfacekit *kit = dev_get_drvdata(dev);
 	int enable;
+	int i, rc;
 	
 	if (kit->ifkit->has_lcd == 0)
 		return -ENODEV;
@@ -253,9 +275,12 @@
 	if (enable) {
 		if (!kit->lcd_files_on) {
 			dev_dbg(&kit->udev->dev, "Adding lcd files\n");
-			device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1);
-			device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2);
-			device_create_file(&kit->intf->dev, &dev_attr_backlight);
+			for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) {
+				rc = device_create_file(kit->dev,
+					&dev_lcd_line_attrs[i]);
+				if (rc)
+					goto out;
+			}
 			kit->lcd_files_on = 1;
 		}
 	} else {
@@ -266,7 +291,13 @@
 	}
 	
 	return count;
+out:
+	while (i-- > 0)
+		device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
+
+	return rc;
 }
+
 static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
 
 static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
@@ -362,44 +393,58 @@
 	for (i=0; i<kit->ifkit->inputs; i++) {
 		if (test_and_clear_bit(i, &kit->input_events)) {
 			sprintf(sysfs_file, "input%d", i + 1);
-			sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+			sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
 		}
 	}
 
 	for (i=0; i<kit->ifkit->sensors; i++) {
 		if (test_and_clear_bit(i, &kit->sensor_events)) {
 			sprintf(sysfs_file, "sensor%d", i + 1);
-			sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+			sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
 		}
 	}
 }
 
+static void do_resubmit(void *data)
+{
+	set_outputs(data);
+}
+
 #define show_set_output(value)		\
-static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf,	\
-							size_t count)	\
+static ssize_t set_output##value(struct device *dev,			\
+					struct device_attribute *attr,	\
+					const char *buf, size_t count)	\
 {									\
-	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct interfacekit *kit = usb_get_intfdata(intf);		\
-	int enabled;							\
+	struct interfacekit *kit = dev_get_drvdata(dev);		\
+	int enable;							\
 	int retval;							\
 									\
-	if (sscanf(buf, "%d", &enabled) < 1)				\
+	if (sscanf(buf, "%d", &enable) < 1)				\
 		return -EINVAL;						\
 									\
-	retval = change_outputs(kit, value - 1, enabled);		\
+	if (enable)							\
+		set_bit(value - 1, &kit->outputs);			\
+	else								\
+		clear_bit(value - 1, &kit->outputs); 			\
+									\
+	retval = set_outputs(kit);					\
 									\
 	return retval ? retval : count;					\
 }									\
 									\
-static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf)	\
+static ssize_t show_output##value(struct device *dev, 			\
+					struct device_attribute *attr,	\
+					char *buf)			\
 {									\
-	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct interfacekit *kit = usb_get_intfdata(intf);		\
+	struct interfacekit *kit = dev_get_drvdata(dev);		\
 									\
 	return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\
-}									\
-static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO,			\
-		show_output##value, set_output##value);
+}
+
+#define output_attr(value)						\
+	__ATTR(output##value, S_IWUGO | S_IRUGO,			\
+		show_output##value, set_output##value)
+
 show_set_output(1);
 show_set_output(2);
 show_set_output(3);
@@ -417,15 +462,24 @@
 show_set_output(15);
 show_set_output(16);
 
+static struct device_attribute dev_output_attrs[] = {
+	output_attr(1), output_attr(2), output_attr(3), output_attr(4),
+	output_attr(5), output_attr(6), output_attr(7), output_attr(8),
+	output_attr(9), output_attr(10), output_attr(11), output_attr(12),
+	output_attr(13), output_attr(14), output_attr(15), output_attr(16)
+};
+
 #define show_input(value)	\
-static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf)	\
+static ssize_t show_input##value(struct device *dev, 			\
+			struct device_attribute *attr, char *buf)	\
 {									\
-	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct interfacekit *kit = usb_get_intfdata(intf);		\
+	struct interfacekit *kit = dev_get_drvdata(dev);		\
 									\
 	return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]);	\
-}									\
-static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
+}
+
+#define input_attr(value)						\
+	__ATTR(input##value, S_IRUGO, show_input##value, NULL)
 
 show_input(1);
 show_input(2);
@@ -444,15 +498,25 @@
 show_input(15);
 show_input(16);
 
+static struct device_attribute dev_input_attrs[] = {
+	input_attr(1), input_attr(2), input_attr(3), input_attr(4),
+	input_attr(5), input_attr(6), input_attr(7), input_attr(8),
+	input_attr(9), input_attr(10), input_attr(11), input_attr(12),
+	input_attr(13), input_attr(14), input_attr(15), input_attr(16)
+};
+
 #define show_sensor(value)	\
-static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf)	\
+static ssize_t show_sensor##value(struct device *dev,			\
+					struct device_attribute *attr,	\
+					char *buf)			\
 {									\
-	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct interfacekit *kit = usb_get_intfdata(intf);		\
+	struct interfacekit *kit = dev_get_drvdata(dev);		\
 									\
 	return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]);	\
-}									\
-static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
+}
+
+#define sensor_attr(value)						\
+	__ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL)
 
 show_sensor(1);
 show_sensor(2);
@@ -463,6 +527,11 @@
 show_sensor(7);
 show_sensor(8);
 
+static struct device_attribute dev_sensor_attrs[] = {
+	sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4),
+	sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8)
+};
+
 static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -471,6 +540,7 @@
 	struct interfacekit *kit;
 	struct driver_interfacekit *ifkit;
 	int pipe, maxp, rc = -ENOMEM;
+	int bit, value, i;
 
 	ifkit = (struct driver_interfacekit *)id->driver_info;
 	if (!ifkit)
@@ -493,6 +563,7 @@
 	if (!kit)
 		goto out;
 
+	kit->dev_no = -1;
 	kit->ifkit = ifkit;
 	kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);
 	if (!kit->data)
@@ -505,6 +576,7 @@
 	kit->udev = usb_get_dev(dev);
 	kit->intf = intf;
 	INIT_WORK(&kit->do_notify, do_notify, kit);
+	INIT_WORK(&kit->do_resubmit, do_resubmit, kit);
 	usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
 			maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
 			interfacekit_irq, kit, endpoint->bInterval);
@@ -513,85 +585,80 @@
 
 	usb_set_intfdata(intf, kit);
 
+        do {
+                bit = find_first_zero_bit(&device_no, sizeof(device_no));
+                value = test_and_set_bit(bit, &device_no);
+        } while(value);
+        kit->dev_no = bit;
+
+        kit->dev = device_create(phidget_class, &kit->udev->dev, 0,
+               		"interfacekit%d", kit->dev_no);
+        if (IS_ERR(kit->dev)) {
+                rc = PTR_ERR(kit->dev);
+                kit->dev = NULL;
+                goto out;
+        }
+	dev_set_drvdata(kit->dev, kit);
+
 	if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
 		rc = -EIO;
 		goto out;
 	}
 
-	if (ifkit->outputs >= 4) {
-		device_create_file(&intf->dev, &dev_attr_output1);
-		device_create_file(&intf->dev, &dev_attr_output2);
-		device_create_file(&intf->dev, &dev_attr_output3);
-		device_create_file(&intf->dev, &dev_attr_output4);
-	}
-	if (ifkit->outputs >= 8) {
-		device_create_file(&intf->dev, &dev_attr_output5);
-		device_create_file(&intf->dev, &dev_attr_output6);
-		device_create_file(&intf->dev, &dev_attr_output7);
-		device_create_file(&intf->dev, &dev_attr_output8);
-	} 
-	if (ifkit->outputs == 16) {
-		device_create_file(&intf->dev, &dev_attr_output9);
-		device_create_file(&intf->dev, &dev_attr_output10);
-		device_create_file(&intf->dev, &dev_attr_output11);
-		device_create_file(&intf->dev, &dev_attr_output12);
-		device_create_file(&intf->dev, &dev_attr_output13);
-		device_create_file(&intf->dev, &dev_attr_output14);
-		device_create_file(&intf->dev, &dev_attr_output15);
-		device_create_file(&intf->dev, &dev_attr_output16);
+	for (i=0; i<ifkit->outputs; i++ ) {
+		rc = device_create_file(kit->dev, &dev_output_attrs[i]);
+		if (rc)
+			goto out2;
 	}
 
-	if (ifkit->inputs >= 4) {
-		device_create_file(&intf->dev, &dev_attr_input1);
-		device_create_file(&intf->dev, &dev_attr_input2);
-		device_create_file(&intf->dev, &dev_attr_input3);
-		device_create_file(&intf->dev, &dev_attr_input4);
-	}
-	if (ifkit->inputs >= 8) {
-		device_create_file(&intf->dev, &dev_attr_input5);
-		device_create_file(&intf->dev, &dev_attr_input6);
-		device_create_file(&intf->dev, &dev_attr_input7);
-		device_create_file(&intf->dev, &dev_attr_input8);
-	}
-	if (ifkit->inputs == 16) {
-		device_create_file(&intf->dev, &dev_attr_input9);
-		device_create_file(&intf->dev, &dev_attr_input10);
-		device_create_file(&intf->dev, &dev_attr_input11);
-		device_create_file(&intf->dev, &dev_attr_input12);
-		device_create_file(&intf->dev, &dev_attr_input13);
-		device_create_file(&intf->dev, &dev_attr_input14);
-		device_create_file(&intf->dev, &dev_attr_input15);
-		device_create_file(&intf->dev, &dev_attr_input16);
+	for (i=0; i<ifkit->inputs; i++ ) {
+		rc = device_create_file(kit->dev, &dev_input_attrs[i]);
+		if (rc)
+			goto out3;
 	}
 
-	if (ifkit->sensors >= 4) {
-		device_create_file(&intf->dev, &dev_attr_sensor1);
-		device_create_file(&intf->dev, &dev_attr_sensor2);
-		device_create_file(&intf->dev, &dev_attr_sensor3);
-		device_create_file(&intf->dev, &dev_attr_sensor4);
+	for (i=0; i<ifkit->sensors; i++ ) {
+		rc = device_create_file(kit->dev, &dev_sensor_attrs[i]);
+		if (rc)
+			goto out4;
 	}
-	if (ifkit->sensors >= 7) {
-		device_create_file(&intf->dev, &dev_attr_sensor5);
-		device_create_file(&intf->dev, &dev_attr_sensor6);
-		device_create_file(&intf->dev, &dev_attr_sensor7);
-	}
-	if (ifkit->sensors == 8)
-		device_create_file(&intf->dev, &dev_attr_sensor8);
 
-	if (ifkit->has_lcd)
-		device_create_file(&intf->dev, &dev_attr_lcd);
+	if (ifkit->has_lcd) {
+		rc = device_create_file(kit->dev, &dev_attr_lcd);
+		if (rc)
+			goto out4;
+
+	}
 
 	dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
 			ifkit->sensors, ifkit->inputs, ifkit->outputs);
 
 	return 0;
 
+out4:
+	while (i-- > 0)
+		device_remove_file(kit->dev, &dev_sensor_attrs[i]);
+
+	i = ifkit->inputs;
+out3:
+	while (i-- > 0)
+		device_remove_file(kit->dev, &dev_input_attrs[i]);
+
+	i = ifkit->outputs;
+out2:
+	while (i-- > 0)
+		device_remove_file(kit->dev, &dev_output_attrs[i]);
 out:
 	if (kit) {
 		if (kit->irq)
 			usb_free_urb(kit->irq);
 		if (kit->data)
 			usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
+		if (kit->dev)
+			device_unregister(kit->dev);
+		if (kit->dev_no >= 0)
+			clear_bit(kit->dev_no, &device_no);
+
 		kfree(kit);
 	}
 
@@ -601,6 +668,7 @@
 static void interfacekit_disconnect(struct usb_interface *interface)
 {
 	struct interfacekit *kit;
+	int i;
 
 	kit = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
@@ -612,74 +680,30 @@
 	usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma);
 
 	cancel_delayed_work(&kit->do_notify);
+	cancel_delayed_work(&kit->do_resubmit);
 
-	if (kit->ifkit->outputs >= 4) {
-		device_remove_file(&interface->dev, &dev_attr_output1);
-		device_remove_file(&interface->dev, &dev_attr_output2);
-		device_remove_file(&interface->dev, &dev_attr_output3);
-		device_remove_file(&interface->dev, &dev_attr_output4);
-	}
-	if (kit->ifkit->outputs >= 8) {
-		device_remove_file(&interface->dev, &dev_attr_output5);
-		device_remove_file(&interface->dev, &dev_attr_output6);
-		device_remove_file(&interface->dev, &dev_attr_output7);
-		device_remove_file(&interface->dev, &dev_attr_output8);
-	}
-	if (kit->ifkit->outputs == 16) {
-		device_remove_file(&interface->dev, &dev_attr_output9);
-		device_remove_file(&interface->dev, &dev_attr_output10);
-		device_remove_file(&interface->dev, &dev_attr_output11);
-		device_remove_file(&interface->dev, &dev_attr_output12);
-		device_remove_file(&interface->dev, &dev_attr_output13);
-		device_remove_file(&interface->dev, &dev_attr_output14);
-		device_remove_file(&interface->dev, &dev_attr_output15);
-		device_remove_file(&interface->dev, &dev_attr_output16);
+	for (i=0; i<kit->ifkit->outputs; i++)
+		device_remove_file(kit->dev, &dev_output_attrs[i]);
+
+	for (i=0; i<kit->ifkit->inputs; i++)
+		device_remove_file(kit->dev, &dev_input_attrs[i]);
+
+	for (i=0; i<kit->ifkit->sensors; i++)
+		device_remove_file(kit->dev, &dev_sensor_attrs[i]);
+
+	if (kit->ifkit->has_lcd) {
+		device_remove_file(kit->dev, &dev_attr_lcd);
+		remove_lcd_files(kit);
 	}
 
-	if (kit->ifkit->inputs >= 4) {
-		device_remove_file(&interface->dev, &dev_attr_input1);
-		device_remove_file(&interface->dev, &dev_attr_input2);
-		device_remove_file(&interface->dev, &dev_attr_input3);
-		device_remove_file(&interface->dev, &dev_attr_input4);
-	}
-	if (kit->ifkit->inputs >= 8) {
-		device_remove_file(&interface->dev, &dev_attr_input5);
-		device_remove_file(&interface->dev, &dev_attr_input6);
-		device_remove_file(&interface->dev, &dev_attr_input7);
-		device_remove_file(&interface->dev, &dev_attr_input8);
-	}
-	if (kit->ifkit->inputs == 16) {
-		device_remove_file(&interface->dev, &dev_attr_input9);
-		device_remove_file(&interface->dev, &dev_attr_input10);
-		device_remove_file(&interface->dev, &dev_attr_input11);
-		device_remove_file(&interface->dev, &dev_attr_input12);
-		device_remove_file(&interface->dev, &dev_attr_input13);
-		device_remove_file(&interface->dev, &dev_attr_input14);
-		device_remove_file(&interface->dev, &dev_attr_input15);
-		device_remove_file(&interface->dev, &dev_attr_input16);
-	}
-
-	if (kit->ifkit->sensors >= 4) {
-		device_remove_file(&interface->dev, &dev_attr_sensor1);
-		device_remove_file(&interface->dev, &dev_attr_sensor2);
-		device_remove_file(&interface->dev, &dev_attr_sensor3);
-		device_remove_file(&interface->dev, &dev_attr_sensor4);
-	}
-	if (kit->ifkit->sensors >= 7) {
-		device_remove_file(&interface->dev, &dev_attr_sensor5);
-		device_remove_file(&interface->dev, &dev_attr_sensor6);
-		device_remove_file(&interface->dev, &dev_attr_sensor7);
-	}
-	if (kit->ifkit->sensors == 8)
-		device_remove_file(&interface->dev, &dev_attr_sensor8);
-
-	if (kit->ifkit->has_lcd)
-		device_remove_file(&interface->dev, &dev_attr_lcd);
+	device_unregister(kit->dev);
 
 	dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
 		kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
 
 	usb_put_dev(kit->udev);
+	clear_bit(kit->dev_no, &device_no);
+
 	kfree(kit);
 }
 
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
new file mode 100644
index 0000000..6b59b62
--- /dev/null
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -0,0 +1,466 @@
+/*
+ * USB Phidget MotorControl driver
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "phidget.h"
+
+#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
+#define DRIVER_DESC "USB PhidgetMotorControl Driver"
+
+#define USB_VENDOR_ID_GLAB		0x06c2
+#define USB_DEVICE_ID_MOTORCONTROL	0x0058
+
+#define URB_INT_SIZE			8
+
+static unsigned long device_no;
+
+struct motorcontrol {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	struct device *dev;
+	int dev_no;
+	u8 inputs[4];
+	s8 desired_speed[2];
+	s8 speed[2];
+	s16 _current[2];
+	s8 acceleration[2];
+	struct urb *irq;
+	unsigned char *data;
+	dma_addr_t data_dma;
+
+	struct work_struct do_notify;
+	unsigned long input_events;
+	unsigned long speed_events;
+	unsigned long exceed_events;
+};
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) },
+	{}
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int set_motor(struct motorcontrol *mc, int motor)
+{
+	u8 *buffer;
+	int speed, speed2, acceleration;
+	int retval;
+
+	buffer = kzalloc(8, GFP_KERNEL);
+	if (!buffer) {
+		dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	acceleration = mc->acceleration[motor] * 10;
+	/* -127 <= speed <= 127 */
+	speed = (mc->desired_speed[motor] * 127) / 100;
+	/* -0x7300 <= speed2 <= 0x7300 */
+	speed2 = (mc->desired_speed[motor] * 230 * 128) / 100;
+
+	buffer[0] = motor;
+	buffer[1] = speed;
+	buffer[2] = acceleration >> 8;
+	buffer[3] = acceleration;
+	buffer[4] = speed2 >> 8;
+	buffer[5] = speed2;
+
+	retval = usb_control_msg(mc->udev,
+			 usb_sndctrlpipe(mc->udev, 0),
+			 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
+
+	if (retval != 8)
+		dev_err(&mc->intf->dev, "usb_control_msg returned %d\n",
+				retval);
+	kfree(buffer);
+
+	return retval < 0 ? retval : 0;
+}
+
+static void motorcontrol_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct motorcontrol *mc = urb->context;
+	unsigned char *buffer = mc->data;
+	int i, level;
+	int status;
+
+	switch (urb->status) {
+	case 0:			/* success */
+		break;
+	case -ECONNRESET:	/* unlink */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	/* -EPIPE:  should clear the halt */
+	default:		/* error */
+		goto resubmit;
+	}
+
+	/* digital inputs */
+	for (i=0; i<4; i++) {
+		level = (buffer[0] >> i) & 1;
+		if (mc->inputs[i] != level) {
+			mc->inputs[i] = level;
+			set_bit(i, &mc->input_events);
+		}
+	}
+
+	/* motor speed */
+	if (buffer[2] == 0) {
+		for (i=0; i<2; i++) {
+		level = ((s8)buffer[4+i]) * 100 / 127;
+			if (mc->speed[i] != level) {
+				mc->speed[i] = level;
+				set_bit(i, &mc->speed_events);
+			}
+		}
+	} else {
+		int index = buffer[3] & 1;
+
+		level = ((s8)buffer[4] << 8) | buffer[5];
+		level = level * 100 / 29440;
+		if (mc->speed[index] != level) {
+			mc->speed[index] = level;
+			set_bit(index, &mc->speed_events);
+		}
+
+		level = ((s8)buffer[6] << 8) | buffer[7];
+		mc->_current[index] = level * 100 / 1572;
+	}
+
+	if (buffer[1] & 1)
+		set_bit(0, &mc->exceed_events);
+
+	if (buffer[1] & 2)
+		set_bit(1, &mc->exceed_events);
+
+	if (mc->input_events || mc->exceed_events || mc->speed_events)
+		schedule_work(&mc->do_notify);
+
+resubmit:
+	status = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (status)
+		dev_err(&mc->intf->dev,
+			"can't resubmit intr, %s-%s/motorcontrol0, status %d",
+			mc->udev->bus->bus_name,
+			mc->udev->devpath, status);
+}
+
+static void do_notify(void *data)
+{
+	struct motorcontrol *mc = data;
+	int i;
+	char sysfs_file[8];
+
+	for (i=0; i<4; i++) {
+		if (test_and_clear_bit(i, &mc->input_events)) {
+			sprintf(sysfs_file, "input%d", i);
+			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
+		}
+	}
+
+	for (i=0; i<2; i++) {
+		if (test_and_clear_bit(i, &mc->speed_events)) {
+			sprintf(sysfs_file, "speed%d", i);
+			sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
+		}
+	}
+
+	for (i=0; i<2; i++) {
+		if (test_and_clear_bit(i, &mc->exceed_events))
+			dev_warn(&mc->intf->dev,
+				"motor #%d exceeds 1.5 Amp current limit\n", i);
+	}
+}
+
+#define show_set_speed(value)		\
+static ssize_t set_speed##value(struct device *dev,			\
+					struct device_attribute *attr,	\
+					const char *buf, size_t count)	\
+{									\
+	struct motorcontrol *mc = dev_get_drvdata(dev);			\
+	int speed;							\
+	int retval;							\
+									\
+	if (sscanf(buf, "%d", &speed) < 1)				\
+		return -EINVAL;						\
+									\
+	if (speed < -100 || speed > 100)				\
+		return -EINVAL;						\
+									\
+	mc->desired_speed[value] = speed;				\
+									\
+	retval = set_motor(mc, value);					\
+									\
+	return retval ? retval : count;					\
+}									\
+									\
+static ssize_t show_speed##value(struct device *dev,			\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+	struct motorcontrol *mc = dev_get_drvdata(dev);			\
+									\
+	return sprintf(buf, "%d\n", mc->speed[value]);			\
+}
+
+#define speed_attr(value) 						\
+	__ATTR(speed##value, S_IWUGO | S_IRUGO, 			\
+		show_speed##value, set_speed##value)
+
+show_set_speed(0);
+show_set_speed(1);
+
+#define show_set_acceleration(value)		\
+static ssize_t set_acceleration##value(struct device *dev, 		\
+					struct device_attribute *attr,	\
+					const char *buf, size_t count)	\
+{									\
+	struct motorcontrol *mc = dev_get_drvdata(dev);			\
+	int acceleration;						\
+	int retval;							\
+									\
+	if (sscanf(buf, "%d", &acceleration) < 1)			\
+		return -EINVAL;						\
+									\
+	if (acceleration < 0 || acceleration > 100)			\
+		return -EINVAL;						\
+									\
+	mc->acceleration[value] = acceleration;				\
+									\
+	retval = set_motor(mc, value);					\
+									\
+	return retval ? retval : count;					\
+}									\
+									\
+static ssize_t show_acceleration##value(struct device *dev,	 	\
+					struct device_attribute *attr,	\
+							char *buf)	\
+{									\
+	struct motorcontrol *mc = dev_get_drvdata(dev);			\
+									\
+	return sprintf(buf, "%d\n", mc->acceleration[value]);		\
+}
+
+#define acceleration_attr(value)	\
+	__ATTR(acceleration##value, S_IWUGO | S_IRUGO,			\
+		show_acceleration##value, set_acceleration##value)
+
+show_set_acceleration(0);
+show_set_acceleration(1);
+
+#define show_current(value)	\
+static ssize_t show_current##value(struct device *dev,			\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+	struct motorcontrol *mc = dev_get_drvdata(dev);			\
+									\
+	return sprintf(buf, "%dmA\n", (int)mc->_current[value]);	\
+}
+
+#define current_attr(value)	\
+	__ATTR(current##value, S_IRUGO, show_current##value, NULL)
+
+show_current(0);
+show_current(1);
+
+#define show_input(value)	\
+static ssize_t show_input##value(struct device *dev,			\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+	struct motorcontrol *mc = dev_get_drvdata(dev);			\
+									\
+	return sprintf(buf, "%d\n", (int)mc->inputs[value]);		\
+}
+
+#define input_attr(value)	\
+	__ATTR(input##value, S_IRUGO, show_input##value, NULL)
+
+show_input(0);
+show_input(1);
+show_input(2);
+show_input(3);
+
+static struct device_attribute dev_attrs[] = {
+	input_attr(0),
+	input_attr(1),
+	input_attr(2),
+	input_attr(3),
+	speed_attr(0),
+	speed_attr(1),
+	acceleration_attr(0),
+	acceleration_attr(1),
+	current_attr(0),
+	current_attr(1)
+};
+
+static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct motorcontrol *mc;
+	int pipe, maxp, rc = -ENOMEM;
+	int bit, value, i;
+
+	interface = intf->cur_altsetting;
+	if (interface->desc.bNumEndpoints != 1)
+		return -ENODEV;
+
+	endpoint = &interface->endpoint[0].desc;
+	if (!(endpoint->bEndpointAddress & 0x80))
+		return -ENODEV;
+
+	/*
+	 * bmAttributes
+	 */
+	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	mc = kzalloc(sizeof(*mc), GFP_KERNEL);
+	if (!mc)
+		goto out;
+
+	mc->dev_no = -1;
+	mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma);
+	if (!mc->data)
+		goto out;
+
+	mc->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!mc->irq)
+		goto out;
+
+	mc->udev = usb_get_dev(dev);
+	mc->intf = intf;
+	mc->acceleration[0] = mc->acceleration[1] = 10;
+	INIT_WORK(&mc->do_notify, do_notify, mc);
+	usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data,
+			maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
+			motorcontrol_irq, mc, endpoint->bInterval);
+	mc->irq->transfer_dma = mc->data_dma;
+	mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	usb_set_intfdata(intf, mc);
+
+	do {
+		bit = find_first_zero_bit(&device_no, sizeof(device_no));
+		value = test_and_set_bit(bit, &device_no);
+	} while(value);
+	mc->dev_no = bit;
+
+	mc->dev = device_create(phidget_class, &mc->udev->dev, 0,
+				"motorcontrol%d", mc->dev_no);
+	if (IS_ERR(mc->dev)) {
+		rc = PTR_ERR(mc->dev);
+		mc->dev = NULL;
+		goto out;
+	}
+
+	dev_set_drvdata(mc->dev, mc);
+
+	if (usb_submit_urb(mc->irq, GFP_KERNEL)) {
+		rc = -EIO;
+		goto out;
+	}
+
+	for (i=0; i<ARRAY_SIZE(dev_attrs); i++) {
+		rc = device_create_file(mc->dev, &dev_attrs[i]);
+		if (rc)
+			goto out2;
+	}
+
+	dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");
+
+	return 0;
+out2:
+	while (i-- > 0)
+		device_remove_file(mc->dev, &dev_attrs[i]);
+out:
+	if (mc) {
+		if (mc->irq)
+			usb_free_urb(mc->irq);
+		if (mc->data)
+			usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
+		if (mc->dev)
+			device_unregister(mc->dev);
+		if (mc->dev_no >= 0)
+			clear_bit(mc->dev_no, &device_no);
+
+		kfree(mc);
+	}
+
+	return rc;
+}
+
+static void motorcontrol_disconnect(struct usb_interface *interface)
+{
+	struct motorcontrol *mc;
+	int i;
+
+	mc = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+	if (!mc)
+		return;
+
+	usb_kill_urb(mc->irq);
+	usb_free_urb(mc->irq);
+	usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma);
+
+	cancel_delayed_work(&mc->do_notify);
+
+	for (i=0; i<ARRAY_SIZE(dev_attrs); i++)
+		device_remove_file(mc->dev, &dev_attrs[i]);
+
+	device_unregister(mc->dev);
+
+	usb_put_dev(mc->udev);
+	clear_bit(mc->dev_no, &device_no);
+	kfree(mc);
+
+	dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");
+}
+
+static struct usb_driver motorcontrol_driver = {
+	.name = "phidgetmotorcontrol",
+	.probe = motorcontrol_probe,
+	.disconnect = motorcontrol_disconnect,
+	.id_table = id_table
+};
+
+static int __init motorcontrol_init(void)
+{
+	int retval = 0;
+
+	retval = usb_register(&motorcontrol_driver);
+	if (retval)
+		err("usb_register failed. Error number %d", retval);
+
+	return retval;
+}
+
+static void __exit motorcontrol_exit(void)
+{
+	usb_deregister(&motorcontrol_driver);
+}
+
+module_init(motorcontrol_init);
+module_exit(motorcontrol_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index c0df79c9..7163f05 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -1,7 +1,7 @@
 /*
  * USB PhidgetServo driver 1.0
  *
- * Copyright (C) 2004 Sean Young <sean@mess.org>
+ * Copyright (C) 2004, 2006 Sean Young <sean@mess.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
@@ -15,14 +15,6 @@
  *
  * CAUTION: Generally you should use 0 < degrees < 180 as anything else
  * is probably beyond the range of your servo and may damage it.
- *
- * Jun 16, 2004: Sean Young <sean@mess.org>
- *  - cleanups
- *  - was using memory after kfree()
- * Aug 8, 2004: Sean Young <sean@mess.org>
- *  - set the highest angle as high as the hardware allows, there are 
- *    some odd servos out there
- *
  */
 
 #include <linux/kernel.h>
@@ -32,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 
+#include "phidget.h"
+
 #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
 #define DRIVER_DESC "USB PhidgetServo Driver"
 
@@ -70,8 +64,12 @@
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
+static int unsigned long device_no;
+
 struct phidget_servo {
 	struct usb_device *udev;
+	struct device *dev;
+	int dev_no;
 	ulong type;
 	int pulse[4];
 	int degrees[4];
@@ -203,16 +201,16 @@
 }
 
 #define show_set(value)	\
-static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr,			\
+static ssize_t set_servo##value (struct device *dev, 			\
+					struct device_attribute *attr,	\
 					const char *buf, size_t count)	\
 {									\
 	int degrees, minutes, retval;					\
-	struct usb_interface *intf = to_usb_interface (dev);		\
-	struct phidget_servo *servo = usb_get_intfdata (intf);		\
+	struct phidget_servo *servo = dev_get_drvdata(dev);		\
 									\
 	minutes = 0;							\
 	/* must at least convert degrees */				\
-	if (sscanf (buf, "%d.%d", &degrees, &minutes) < 1) {		\
+	if (sscanf(buf, "%d.%d", &degrees, &minutes) < 1) {		\
 		return -EINVAL;						\
 	}								\
 									\
@@ -220,86 +218,127 @@
 		return -EINVAL;						\
 									\
 	if (servo->type & SERVO_VERSION_30)				\
-		retval = change_position_v30 (servo, value, degrees, 	\
+		retval = change_position_v30(servo, value, degrees, 	\
 							minutes);	\
 	else 								\
-		retval = change_position_v20 (servo, value, degrees, 	\
+		retval = change_position_v20(servo, value, degrees, 	\
 							minutes);	\
 									\
 	return retval < 0 ? retval : count;				\
 }									\
 									\
-static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf) 	\
+static ssize_t show_servo##value (struct device *dev,			\
+					struct device_attribute *attr,	\
+					char *buf) 			\
 {									\
-	struct usb_interface *intf = to_usb_interface (dev);		\
-	struct phidget_servo *servo = usb_get_intfdata (intf);		\
+	struct phidget_servo *servo = dev_get_drvdata(dev);		\
 									\
-	return sprintf (buf, "%d.%02d\n", servo->degrees[value],	\
+	return sprintf(buf, "%d.%02d\n", servo->degrees[value],		\
 				servo->minutes[value]);			\
-}									\
-static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO,			\
-	  show_servo##value, set_servo##value);
+}
 
+#define servo_attr(value)						\
+	__ATTR(servo##value, S_IWUGO | S_IRUGO,				\
+		show_servo##value, set_servo##value)
 show_set(0);
 show_set(1);
 show_set(2);
 show_set(3);
 
+static struct device_attribute dev_attrs[] = {
+	servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3)
+};
+
 static int
 servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
 	struct phidget_servo *dev;
+	int bit, value, rc;
+	int servo_count, i;
 
 	dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
 	if (dev == NULL) {
 		dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out;
 	}
 
 	dev->udev = usb_get_dev(udev);
 	dev->type = id->driver_info;
+	dev->dev_no = -1;
 	usb_set_intfdata(interface, dev);
 
-	device_create_file(&interface->dev, &dev_attr_servo0);
-	if (dev->type & SERVO_COUNT_QUAD) {
-		device_create_file(&interface->dev, &dev_attr_servo1);
-		device_create_file(&interface->dev, &dev_attr_servo2);
-		device_create_file(&interface->dev, &dev_attr_servo3);
+        do {
+                bit = find_first_zero_bit(&device_no, sizeof(device_no));
+                value = test_and_set_bit(bit, &device_no);
+        } while (value);
+	dev->dev_no = bit;
+
+	dev->dev = device_create(phidget_class, &dev->udev->dev, 0,
+				 "servo%d", dev->dev_no);
+	if (IS_ERR(dev->dev)) {
+		rc = PTR_ERR(dev->dev);
+		dev->dev = NULL;
+		goto out;
+	}
+
+	servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
+
+	for (i=0; i<servo_count; i++) {
+		rc = device_create_file(dev->dev, &dev_attrs[i]);
+		if (rc)
+			goto out2;
 	}
 
 	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",
-		dev->type & SERVO_COUNT_QUAD ? 4 : 1,
-		dev->type & SERVO_VERSION_30 ? 3 : 2);
+		servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
 
-	if(!(dev->type & SERVO_VERSION_30))
+	if (!(dev->type & SERVO_VERSION_30))
 		dev_info(&interface->dev,
 			 "WARNING: v2.0 not tested! Please report if it works.\n");
 
 	return 0;
+out2:
+	while (i-- > 0)
+		device_remove_file(dev->dev, &dev_attrs[i]);
+out:
+	if (dev) {
+		if (dev->dev)
+			device_unregister(dev->dev);
+		if (dev->dev_no >= 0)
+			clear_bit(dev->dev_no, &device_no);
+
+		kfree(dev);
+	}
+
+	return rc;
 }
 
 static void
 servo_disconnect(struct usb_interface *interface)
 {
 	struct phidget_servo *dev;
+	int servo_count, i;
 
 	dev = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
-	device_remove_file(&interface->dev, &dev_attr_servo0);
-	if (dev->type & SERVO_COUNT_QUAD) {
-		device_remove_file(&interface->dev, &dev_attr_servo1);
-		device_remove_file(&interface->dev, &dev_attr_servo2);
-		device_remove_file(&interface->dev, &dev_attr_servo3);
-	}
+	if (!dev)
+		return;
 
+	servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
+
+	for (i=0; i<servo_count; i++)
+		device_remove_file(dev->dev, &dev_attrs[i]);
+
+	device_unregister(dev->dev);
 	usb_put_dev(dev->udev);
 
 	dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",
-		dev->type & SERVO_COUNT_QUAD ? 4 : 1,
-		dev->type & SERVO_VERSION_30 ? 3 : 2);
+		servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
 
+	clear_bit(dev->dev_no, &device_no);
 	kfree(dev);
 }
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index e16582f..a44124c 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3179,7 +3179,7 @@
 }
 #endif
 
-static struct file_operations usb_sisusb_fops = {
+static const struct file_operations usb_sisusb_fops = {
 	.owner =	THIS_MODULE,
 	.open =		sisusb_open,
 	.release =	sisusb_release,
diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h
new file mode 100644
index 0000000..551ba89
--- /dev/null
+++ b/drivers/usb/misc/usb_u132.h
@@ -0,0 +1,97 @@
+/*
+* Common Header File for the Elan Digital Systems U132 adapter
+* this file should be included by both the "ftdi-u132" and
+* the "u132-hcd" modules.
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+*(http://www.elandigitalsystems.com)
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+*(tony.olech@elandigitalsystems.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, version 2.
+*
+*
+* The driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB client drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+* The driver consists of two modules, the "ftdi-u132" module is
+* a USB client driver that interfaces to the FTDI chip within
+* the U132 adapter manufactured by Elan Digital Systems, and the
+* "u132-hcd" module is a USB host controller driver that talks
+* to the OHCI controller within CardBus card that are inserted
+* in the U132 adapter.
+*
+* The "ftdi-u132" module should be loaded automatically by the
+* hot plug system when the U132 adapter is plugged in. The module
+* initialises the adapter which mostly consists of synchronising
+* the FTDI chip, before continuously polling the adapter to detect
+* PC card insertions. As soon as a PC card containing a recognised
+* OHCI controller is seen the "ftdi-u132" module explicitly requests
+* the kernel to load the "u132-hcd" module.
+*
+* The "ftdi-u132" module provides the interface to the inserted
+* PC card and the "u132-hcd" module uses the API to send and recieve
+* data. The API features call-backs, so that part of the "u132-hcd"
+* module code will run in the context of one of the kernel threads
+* of the "ftdi-u132" module.
+*
+*/
+int ftdi_elan_switch_on_diagnostics(int number);
+void ftdi_elan_gone_away(struct platform_device *pdev);
+void start_usb_lock_device_tracing(void);
+struct u132_platform_data {
+        u16 vendor;
+        u16 device;
+        u8 potpg;
+        void (*port_power) (struct device *dev, int is_on);
+        void (*reset) (struct device *dev);
+};
+int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
+        void *endp);
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index e095772..dbaca9f 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -239,7 +239,7 @@
 	return retval;
 }
 
-static struct file_operations lcd_fops = {
+static const struct file_operations lcd_fops = {
         .owner =        THIS_MODULE,
         .read =         lcd_read,
         .write =        lcd_write,
@@ -290,9 +290,7 @@
 		endpoint = &iface_desc->endpoint[i].desc;
 
 		if (!dev->bulk_in_endpointAddr &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-					== USB_ENDPOINT_XFER_BULK)) {
+		    usb_endpoint_is_bulk_in(endpoint)) {
 			/* we found a bulk in endpoint */
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			dev->bulk_in_size = buffer_size;
@@ -305,9 +303,7 @@
 		}
 
 		if (!dev->bulk_out_endpointAddr &&
-		    !(endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-					== USB_ENDPOINT_XFER_BULK)) {
+		    usb_endpoint_is_bulk_out(endpoint)) {
 			/* we found a bulk out endpoint */
 			dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
 		}
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 0c5ee0a..49c5c5c 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -108,22 +108,34 @@
 	dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL);
 	if (dev == NULL) {
 		dev_err(&interface->dev, "Out of memory\n");
-		goto error;
+		goto error_mem;
 	}
 
 	dev->udev = usb_get_dev(udev);
 
 	usb_set_intfdata (interface, dev);
 
-	device_create_file(&interface->dev, &dev_attr_blue);
-	device_create_file(&interface->dev, &dev_attr_red);
-	device_create_file(&interface->dev, &dev_attr_green);
+	retval = device_create_file(&interface->dev, &dev_attr_blue);
+	if (retval)
+		goto error;
+	retval = device_create_file(&interface->dev, &dev_attr_red);
+	if (retval)
+		goto error;
+	retval = device_create_file(&interface->dev, &dev_attr_green);
+	if (retval)
+		goto error;
 
 	dev_info(&interface->dev, "USB LED device now attached\n");
 	return 0;
 
 error:
+	device_remove_file(&interface->dev, &dev_attr_blue);
+	device_remove_file(&interface->dev, &dev_attr_red);
+	device_remove_file(&interface->dev, &dev_attr_green);
+	usb_set_intfdata (interface, NULL);
+	usb_put_dev(dev->udev);
 	kfree(dev);
+error_mem:
 	return retval;
 }
 
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 275a66f..394bbf2 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -265,7 +265,6 @@
 	ubus->mon_bus = NULL;
 	mbus->u_bus = NULL;
 	mb();
-	// usb_bus_put(ubus);
 }
 
 /*
@@ -297,12 +296,12 @@
 	INIT_LIST_HEAD(&mbus->r_list);
 
 	/*
-	 * This usb_bus_get here is superfluous, because we receive
-	 * a notification if usb_bus is about to be removed.
+	 * We don't need to take a reference to ubus, because we receive
+	 * a notification if the bus is about to be removed.
 	 */
-	// usb_bus_get(ubus);
 	mbus->u_bus = ubus;
 	ubus->mon_bus = mbus;
+	mbus->uses_dma = ubus->uses_dma;
 
 	rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
 	if (rc <= 0 || rc >= NAMESZ)
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
index 86ad2b3..f6d1491 100644
--- a/drivers/usb/mon/mon_stat.c
+++ b/drivers/usb/mon/mon_stat.c
@@ -62,7 +62,7 @@
 	return 0;
 }
 
-struct file_operations mon_fops_stat = {
+const struct file_operations mon_fops_stat = {
 	.owner =	THIS_MODULE,
 	.open =		mon_stat_open,
 	.llseek =	no_llseek,
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 2fd39b4..7a2346c 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -75,13 +75,13 @@
  */
 
 static inline char mon_text_get_setup(struct mon_event_text *ep,
-    struct urb *urb, char ev_type)
+    struct urb *urb, char ev_type, struct mon_bus *mbus)
 {
 
 	if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
 		return '-';
 
-	if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
+	if (mbus->uses_dma && (urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
 		return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
 	if (urb->setup_packet == NULL)
 		return 'Z';	/* '0' would be not as pretty. */
@@ -91,7 +91,7 @@
 }
 
 static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
-    int len, char ev_type)
+    int len, char ev_type, struct mon_bus *mbus)
 {
 	int pipe = urb->pipe;
 
@@ -117,7 +117,7 @@
 	 * contain non-NULL garbage in case the upper level promised to
 	 * set DMA for the HCD.
 	 */
-	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+	if (mbus->uses_dma && (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
 		return mon_dmapeek(ep->data, urb->transfer_dma, len);
 
 	if (urb->transfer_buffer == NULL)
@@ -161,8 +161,9 @@
 	/* Collecting status makes debugging sense for submits, too */
 	ep->status = urb->status;
 
-	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type);
-	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
+	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
+	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
+			rp->r.m_bus);
 
 	rp->nevents++;
 	list_add_tail(&ep->e_link, &rp->e_list);
@@ -435,7 +436,7 @@
 	return 0;
 }
 
-struct file_operations mon_fops_text = {
+const struct file_operations mon_fops_text = {
 	.owner =	THIS_MODULE,
 	.open =		mon_text_open,
 	.llseek =	no_llseek,
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 33678c2..ab9d02d 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -20,6 +20,7 @@
 	struct dentry *dent_s;		/* Debugging file */
 	struct dentry *dent_t;		/* Text interface file */
 	struct usb_bus *u_bus;
+	int uses_dma;
 
 	/* Ref */
 	int nreaders;			/* Under mon_lock AND mbus->lock */
@@ -53,7 +54,7 @@
 
 extern struct mutex mon_lock;
 
-extern struct file_operations mon_fops_text;
-extern struct file_operations mon_fops_stat;
+extern const struct file_operations mon_fops_text;
+extern const struct file_operations mon_fops_stat;
 
 #endif /* __USB_MON_H */
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 2e2bbc00..9c0eacf 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -1,7 +1,8 @@
 /*
  * ASIX AX8817X based USB 2.0 Ethernet Devices
- * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
  * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
  * Copyright (c) 2002-2003 TiVo Inc.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -36,6 +37,9 @@
 
 #include "usbnet.h"
 
+#define DRIVER_VERSION "14-Jun-2006"
+static const char driver_name [] = "asix";
+
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
 
 #define AX_CMD_SET_SW_MII		0x06
@@ -46,23 +50,25 @@
 #define AX_CMD_WRITE_EEPROM		0x0c
 #define AX_CMD_WRITE_ENABLE		0x0d
 #define AX_CMD_WRITE_DISABLE		0x0e
+#define AX_CMD_READ_RX_CTL		0x0f
 #define AX_CMD_WRITE_RX_CTL		0x10
 #define AX_CMD_READ_IPG012		0x11
 #define AX_CMD_WRITE_IPG0		0x12
 #define AX_CMD_WRITE_IPG1		0x13
+#define AX_CMD_READ_NODE_ID		0x13
 #define AX_CMD_WRITE_IPG2		0x14
 #define AX_CMD_WRITE_MULTI_FILTER	0x16
-#define AX_CMD_READ_NODE_ID		0x17
+#define AX88172_CMD_READ_NODE_ID	0x17
 #define AX_CMD_READ_PHY_ID		0x19
 #define AX_CMD_READ_MEDIUM_STATUS	0x1a
 #define AX_CMD_WRITE_MEDIUM_MODE	0x1b
 #define AX_CMD_READ_MONITOR_MODE	0x1c
 #define AX_CMD_WRITE_MONITOR_MODE	0x1d
+#define AX_CMD_READ_GPIOS		0x1e
 #define AX_CMD_WRITE_GPIOS		0x1f
 #define AX_CMD_SW_RESET			0x20
 #define AX_CMD_SW_PHY_STATUS		0x21
 #define AX_CMD_SW_PHY_SELECT		0x22
-#define AX88772_CMD_READ_NODE_ID	0x13
 
 #define AX_MONITOR_MODE			0x01
 #define AX_MONITOR_LINK			0x02
@@ -70,15 +76,15 @@
 #define AX_MONITOR_HSFS			0x10
 
 /* AX88172 Medium Status Register values */
-#define AX_MEDIUM_FULL_DUPLEX		0x02
-#define AX_MEDIUM_TX_ABORT_ALLOW	0x04
-#define AX_MEDIUM_FLOW_CONTROL_EN	0x10
+#define AX88172_MEDIUM_FD		0x02
+#define AX88172_MEDIUM_TX		0x04
+#define AX88172_MEDIUM_FC		0x10
+#define AX88172_MEDIUM_DEFAULT \
+		( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC )
 
 #define AX_MCAST_FILTER_SIZE		8
 #define AX_MAX_MCAST			64
 
-#define AX_EEPROM_LEN			0x40
-
 #define AX_SWRESET_CLEAR		0x00
 #define AX_SWRESET_RR			0x01
 #define AX_SWRESET_RT			0x02
@@ -92,23 +98,78 @@
 #define AX88772_IPG1_DEFAULT		0x0c
 #define AX88772_IPG2_DEFAULT		0x12
 
-#define AX88772_MEDIUM_FULL_DUPLEX	0x0002
-#define AX88772_MEDIUM_RESERVED		0x0004
-#define AX88772_MEDIUM_RX_FC_ENABLE	0x0010
-#define AX88772_MEDIUM_TX_FC_ENABLE	0x0020
-#define AX88772_MEDIUM_PAUSE_FORMAT	0x0080
-#define AX88772_MEDIUM_RX_ENABLE	0x0100
-#define AX88772_MEDIUM_100MB		0x0200
-#define AX88772_MEDIUM_DEFAULT	\
-	(AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
-	 AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
-	 AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
+/* AX88772 & AX88178 Medium Mode Register */
+#define AX_MEDIUM_PF		0x0080
+#define AX_MEDIUM_JFE		0x0040
+#define AX_MEDIUM_TFC		0x0020
+#define AX_MEDIUM_RFC		0x0010
+#define AX_MEDIUM_ENCK		0x0008
+#define AX_MEDIUM_AC		0x0004
+#define AX_MEDIUM_FD		0x0002
+#define AX_MEDIUM_GM		0x0001
+#define AX_MEDIUM_SM		0x1000
+#define AX_MEDIUM_SBP		0x0800
+#define AX_MEDIUM_PS		0x0200
+#define AX_MEDIUM_RE		0x0100
 
-#define AX_EEPROM_MAGIC			0xdeadbeef
+#define AX88178_MEDIUM_DEFAULT	\
+	(AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
+	 AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
+	 AX_MEDIUM_RE )
+
+#define AX88772_MEDIUM_DEFAULT	\
+	(AX_MEDIUM_FD | AX_MEDIUM_RFC | \
+	 AX_MEDIUM_TFC | AX_MEDIUM_PS | \
+	 AX_MEDIUM_AC | AX_MEDIUM_RE )
+
+/* AX88772 & AX88178 RX_CTL values */
+#define AX_RX_CTL_SO			0x0080
+#define AX_RX_CTL_AP			0x0020
+#define AX_RX_CTL_AM			0x0010
+#define AX_RX_CTL_AB			0x0008
+#define AX_RX_CTL_SEP			0x0004
+#define AX_RX_CTL_AMALL			0x0002
+#define AX_RX_CTL_PRO			0x0001
+#define AX_RX_CTL_MFB_2048		0x0000
+#define AX_RX_CTL_MFB_4096		0x0100
+#define AX_RX_CTL_MFB_8192		0x0200
+#define AX_RX_CTL_MFB_16384		0x0300
+
+#define AX_DEFAULT_RX_CTL	\
+	(AX_RX_CTL_SO | AX_RX_CTL_AB )
+
+/* GPIO 0 .. 2 toggles */
+#define AX_GPIO_GPO0EN		0x01	/* GPIO0 Output enable */
+#define AX_GPIO_GPO_0		0x02	/* GPIO0 Output value */
+#define AX_GPIO_GPO1EN		0x04	/* GPIO1 Output enable */
+#define AX_GPIO_GPO_1		0x08	/* GPIO1 Output value */
+#define AX_GPIO_GPO2EN		0x10	/* GPIO2 Output enable */
+#define AX_GPIO_GPO_2		0x20	/* GPIO2 Output value */
+#define AX_GPIO_RESERVED	0x40	/* Reserved */
+#define AX_GPIO_RSE		0x80	/* Reload serial EEPROM */
+
+#define AX_EEPROM_MAGIC		0xdeadbeef
+#define AX88172_EEPROM_LEN	0x40
+#define AX88772_EEPROM_LEN	0xff
+
+#define PHY_MODE_MARVELL	0x0000
+#define MII_MARVELL_LED_CTRL	0x0018
+#define MII_MARVELL_STATUS	0x001b
+#define MII_MARVELL_CTRL	0x0014
+
+#define MARVELL_LED_MANUAL	0x0019
+
+#define MARVELL_STATUS_HWCFG	0x0004
+
+#define MARVELL_CTRL_TXDELAY	0x0002
+#define MARVELL_CTRL_RXDELAY	0x0080
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct asix_data {
 	u8 multi_filter[AX_MCAST_FILTER_SIZE];
+	u8 phymode;
+	u8 ledmode;
+	u8 eeprom_len;
 };
 
 struct ax88172_int_data {
@@ -122,6 +183,8 @@
 static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 			    u16 size, void *data)
 {
+	devdbg(dev,"asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+		cmd, value, index, size);
 	return usb_control_msg(
 		dev->udev,
 		usb_rcvctrlpipe(dev->udev, 0),
@@ -137,6 +200,8 @@
 static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 			     u16 size, void *data)
 {
+	devdbg(dev,"asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+		cmd, value, index, size);
 	return usb_control_msg(
 		dev->udev,
 		usb_sndctrlpipe(dev->udev, 0),
@@ -161,65 +226,139 @@
 	usb_free_urb(urb);
 }
 
-static inline int asix_set_sw_mii(struct usbnet *dev)
+static void
+asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+				    u16 size, void *data)
 {
-	int ret;
-	ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
-	if (ret < 0)
-		devdbg(dev, "Failed to enable software MII access");
-	return ret;
-}
+	struct usb_ctrlrequest *req;
+	int status;
+	struct urb *urb;
 
-static inline int asix_set_hw_mii(struct usbnet *dev)
-{
-	int ret;
-	ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
-	if (ret < 0)
-		devdbg(dev, "Failed to enable hardware MII access");
-	return ret;
-}
-
-static inline int asix_get_phyid(struct usbnet *dev)
-{
-	int ret = 0;
-	void *buf;
-
-	buf = kmalloc(2, GFP_KERNEL);
-	if (!buf)
-		goto out1;
-
-	if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID,
-				    0, 0, 2, buf)) < 2) {
-		devdbg(dev, "Error reading PHYID register: %02x", ret);
-		goto out2;
+	devdbg(dev,"asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+		cmd, value, index, size);
+	if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+		deverr(dev, "Error allocating URB in write_cmd_async!");
+		return;
 	}
-	ret = *((u8 *)buf + 1);
-out2:
-	kfree(buf);
-out1:
-	return ret;
+
+	if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
+		deverr(dev, "Failed to allocate memory for control request");
+		usb_free_urb(urb);
+		return;
+	}
+
+	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+	req->bRequest = cmd;
+	req->wValue = value;
+	req->wIndex = index;
+	req->wLength = size;
+
+	usb_fill_control_urb(urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)req, data, size,
+			     asix_async_cmd_callback, req);
+
+	if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+		deverr(dev, "Error submitting the control message: status=%d",
+				status);
+		kfree(req);
+		usb_free_urb(urb);
+	}
 }
 
-static int asix_sw_reset(struct usbnet *dev, u8 flags)
+static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
-	int ret;
+	u8  *head;
+	u32  header;
+	char *packet;
+	struct sk_buff *ax_skb;
+	u16 size;
 
-        ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
-	if (ret < 0)
-		devdbg(dev,"Failed to send software reset: %02x", ret);
+	head = (u8 *) skb->data;
+	memcpy(&header, head, sizeof(header));
+	le32_to_cpus(&header);
+	packet = head + sizeof(header);
 
-	return ret;
+	skb_pull(skb, 4);
+
+	while (skb->len > 0) {
+		if ((short)(header & 0x0000ffff) !=
+		    ~((short)((header & 0xffff0000) >> 16))) {
+			deverr(dev,"asix_rx_fixup() Bad Header Length");
+		}
+		/* get the packet length */
+		size = (u16) (header & 0x0000ffff);
+
+		if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+			return 2;
+		if (size > ETH_FRAME_LEN) {
+			deverr(dev,"asix_rx_fixup() Bad RX Length %d", size);
+			return 0;
+		}
+		ax_skb = skb_clone(skb, GFP_ATOMIC);
+		if (ax_skb) {
+			ax_skb->len = size;
+			ax_skb->data = packet;
+			ax_skb->tail = packet + size;
+			usbnet_skb_return(dev, ax_skb);
+		} else {
+			return 0;
+		}
+
+		skb_pull(skb, (size + 1) & 0xfffe);
+
+		if (skb->len == 0)
+			break;
+
+		head = (u8 *) skb->data;
+		memcpy(&header, head, sizeof(header));
+		le32_to_cpus(&header);
+		packet = head + sizeof(header);
+		skb_pull(skb, 4);
+	}
+
+	if (skb->len < 0) {
+		deverr(dev,"asix_rx_fixup() Bad SKB Length %d", skb->len);
+		return 0;
+	}
+	return 1;
 }
 
-static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
+static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+					gfp_t flags)
 {
-	int ret;
+	int padlen;
+	int headroom = skb_headroom(skb);
+	int tailroom = skb_tailroom(skb);
+	u32 packet_len;
+	u32 padbytes = 0xffff0000;
 
-	ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
-	if (ret < 0)
-                devdbg(dev, "Failed to write RX_CTL mode: %02x", ret);
+	padlen = ((skb->len + 4) % 512) ? 0 : 4;
 
-	return ret;
+	if ((!skb_cloned(skb))
+	    && ((headroom + tailroom) >= (4 + padlen))) {
+		if ((headroom < 4) || (tailroom < padlen)) {
+			skb->data = memmove(skb->head + 4, skb->data, skb->len);
+			skb->tail = skb->data + skb->len;
+		}
+	} else {
+		struct sk_buff *skb2;
+		skb2 = skb_copy_expand(skb, 4, padlen, flags);
+		dev_kfree_skb_any(skb);
+		skb = skb2;
+		if (!skb)
+			return NULL;
+	}
+
+	skb_push(skb, 4);
+	packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+	memcpy(skb->data, &packet_len, sizeof(packet_len));
+
+	if ((skb->len % 512) == 0) {
+		memcpy( skb->tail, &padbytes, sizeof(padbytes));
+		skb_put(skb, sizeof(padbytes));
+	}
+	return skb;
 }
 
 static void asix_status(struct usbnet *dev, struct urb *urb)
@@ -242,55 +381,157 @@
 	}
 }
 
-static void
-asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-				    u16 size, void *data)
+static inline int asix_set_sw_mii(struct usbnet *dev)
 {
-	struct usb_ctrlrequest *req;
-	int status;
-	struct urb *urb;
-
-	if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
-		devdbg(dev, "Error allocating URB in write_cmd_async!");
-		return;
-	}
-
-	if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
-		deverr(dev, "Failed to allocate memory for control request");
-		usb_free_urb(urb);
-		return;
-	}
-
-	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-	req->bRequest = cmd;
-	req->wValue = cpu_to_le16(value);
-	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,
-			     asix_async_cmd_callback, req);
-
-	if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-		deverr(dev, "Error submitting the control message: status=%d",
-				status);
-		kfree(req);
-		usb_free_urb(urb);
-	}
+	int ret;
+	ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
+	if (ret < 0)
+		deverr(dev, "Failed to enable software MII access");
+	return ret;
 }
 
+static inline int asix_set_hw_mii(struct usbnet *dev)
+{
+	int ret;
+	ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
+	if (ret < 0)
+		deverr(dev, "Failed to enable hardware MII access");
+	return ret;
+}
+
+static inline int asix_get_phy_addr(struct usbnet *dev)
+{
+	int ret = 0;
+	void *buf;
+
+	devdbg(dev, "asix_get_phy_addr()");
+
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		goto out1;
+
+	if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID,
+				    0, 0, 2, buf)) < 2) {
+		deverr(dev, "Error reading PHYID register: %02x", ret);
+		goto out2;
+	}
+	devdbg(dev, "asix_get_phy_addr() returning 0x%04x", *((u16 *)buf));
+	ret = *((u8 *)buf + 1);
+out2:
+	kfree(buf);
+out1:
+	return ret;
+}
+
+static int asix_sw_reset(struct usbnet *dev, u8 flags)
+{
+	int ret;
+
+        ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
+	if (ret < 0)
+		deverr(dev,"Failed to send software reset: %02x", ret);
+
+	return ret;
+}
+
+static u16 asix_read_rx_ctl(struct usbnet *dev)
+{
+	u16 ret = 0;
+	void *buf;
+
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		goto out1;
+
+	if ((ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL,
+				    0, 0, 2, buf)) < 2) {
+		deverr(dev, "Error reading RX_CTL register: %02x", ret);
+		goto out2;
+	}
+	ret = le16_to_cpu(*((u16 *)buf));
+out2:
+	kfree(buf);
+out1:
+	return ret;
+}
+
+static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
+{
+	int ret;
+
+	devdbg(dev,"asix_write_rx_ctl() - mode = 0x%04x", mode);
+	ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
+	if (ret < 0)
+		deverr(dev, "Failed to write RX_CTL mode to 0x%04x: %02x",
+		       mode, ret);
+
+	return ret;
+}
+
+static u16 asix_read_medium_status(struct usbnet *dev)
+{
+	u16 ret = 0;
+	void *buf;
+
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		goto out1;
+
+	if ((ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS,
+				    0, 0, 2, buf)) < 2) {
+		deverr(dev, "Error reading Medium Status register: %02x", ret);
+		goto out2;
+	}
+	ret = le16_to_cpu(*((u16 *)buf));
+out2:
+	kfree(buf);
+out1:
+	return ret;
+}
+
+static int asix_write_medium_mode(struct usbnet *dev, u16 mode)
+{
+	int ret;
+
+	devdbg(dev,"asix_write_medium_mode() - mode = 0x%04x", mode);
+	ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+	if (ret < 0)
+		deverr(dev, "Failed to write Medium Mode mode to 0x%04x: %02x",
+			mode, ret);
+
+	return ret;
+}
+
+static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep)
+{
+	int ret;
+
+	devdbg(dev,"asix_write_gpio() - value = 0x%04x", value);
+	ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
+	if (ret < 0)
+		deverr(dev, "Failed to write GPIO value 0x%04x: %02x",
+			value, ret);
+
+	if (sleep)
+		msleep(sleep);
+
+	return ret;
+}
+
+/*
+ * AX88772 & AX88178 have a 16-bit RX_CTL value
+ */
 static void asix_set_multicast(struct net_device *net)
 {
 	struct usbnet *dev = netdev_priv(net);
 	struct asix_data *data = (struct asix_data *)&dev->data;
-	u8 rx_ctl = 0x8c;
+	u16 rx_ctl = AX_DEFAULT_RX_CTL;
 
 	if (net->flags & IFF_PROMISC) {
-		rx_ctl |= 0x01;
+		rx_ctl |= AX_RX_CTL_PRO;
 	} else if (net->flags & IFF_ALLMULTI
 		   || net->mc_count > AX_MAX_MCAST) {
-		rx_ctl |= 0x02;
+		rx_ctl |= AX_RX_CTL_AMALL;
 	} else if (net->mc_count == 0) {
 		/* just broadcast and directed */
 	} else {
@@ -317,7 +558,7 @@
 		asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
 				   AX_MCAST_FILTER_SIZE, data->multi_filter);
 
-		rx_ctl |= 0x10;
+		rx_ctl |= AX_RX_CTL_AM;
 	}
 
 	asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
@@ -333,50 +574,43 @@
 				(__u16)loc, 2, (u16 *)&res);
 	asix_set_hw_mii(dev);
 
-	return res & 0xffff;
-}
+	devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res & 0xffff));
 
-/* same as above, but converts resulting value to cpu byte order */
-static int asix_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
-{
-	return le16_to_cpu(asix_mdio_read(netdev,phy_id, loc));
+	return le16_to_cpu(res & 0xffff);
 }
 
 static void
 asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
 {
 	struct usbnet *dev = netdev_priv(netdev);
-	u16 res = val;
+	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);
 	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);
 }
 
-/* same as above, but converts new value to le16 byte order before writing */
-static void
-asix_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
+static u32 asix_get_phyid(struct usbnet *dev)
 {
-	asix_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
-}
+	int phy_reg;
+	u32 phy_id;
 
-static int ax88172_link_reset(struct usbnet *dev)
-{
-	u16 lpa;
-	u16 adv;
-	u16 res;
-	u8 mode;
+	phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
+	if (phy_reg < 0)
+		return 0;
 
-	mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
-	lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-	adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
-	res = mii_nway_result(lpa|adv);
-	if (res & LPA_DUPLEX)
-		mode |= AX_MEDIUM_FULL_DUPLEX;
-	asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+	phy_id = (phy_reg & 0xffff) << 16;
 
-	return 0;
+	phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
+	if (phy_reg < 0)
+		return 0;
+
+	phy_id |= (phy_reg & 0xffff);
+
+	return phy_id;
 }
 
 static void
@@ -423,7 +657,10 @@
 
 static int asix_get_eeprom_len(struct net_device *net)
 {
-	return AX_EEPROM_LEN;
+	struct usbnet *dev = netdev_priv(net);
+	struct asix_data *data = (struct asix_data *)&dev->data;
+
+	return data->eeprom_len;
 }
 
 static int asix_get_eeprom(struct net_device *net,
@@ -453,9 +690,14 @@
 static void asix_get_drvinfo (struct net_device *net,
 				 struct ethtool_drvinfo *info)
 {
+	struct usbnet *dev = netdev_priv(net);
+	struct asix_data *data = (struct asix_data *)&dev->data;
+
 	/* Inherit standard device info */
 	usbnet_get_drvinfo(net, info);
-	info->eedump_len = 0x3e;
+	strncpy (info->driver, driver_name, sizeof info->driver);
+	strncpy (info->version, DRIVER_VERSION, sizeof info->version);
+	info->eedump_len = data->eeprom_len;
 }
 
 static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
@@ -468,8 +710,34 @@
 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);
 
-	return 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);
+
+	return mii_link_ok(&dev->mii);
+}
+
+static int asix_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);
 }
 
 /* We need to override some ethtool_ops so we require our
@@ -477,7 +745,8 @@
    devices that may be connected at the same time. */
 static struct ethtool_ops ax88172_ethtool_ops = {
 	.get_drvinfo		= asix_get_drvinfo,
-	.get_link		= ethtool_op_get_link,
+	.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,
@@ -488,11 +757,66 @@
 	.set_settings		= asix_set_settings,
 };
 
-static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+static void ax88172_set_multicast(struct net_device *net)
 {
 	struct usbnet *dev = netdev_priv(net);
+	struct asix_data *data = (struct asix_data *)&dev->data;
+	u8 rx_ctl = 0x8c;
 
-	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+	if (net->flags & IFF_PROMISC) {
+		rx_ctl |= 0x01;
+	} else if (net->flags & IFF_ALLMULTI
+		   || net->mc_count > AX_MAX_MCAST) {
+		rx_ctl |= 0x02;
+	} 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, AX_MCAST_FILTER_SIZE);
+
+		/* 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;
+		}
+
+		asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+				   AX_MCAST_FILTER_SIZE, data->multi_filter);
+
+		rx_ctl |= 0x10;
+	}
+
+	asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+}
+
+static int ax88172_link_reset(struct usbnet *dev)
+{
+	u8 mode;
+	struct ethtool_cmd ecmd;
+
+	mii_check_media(&dev->mii, 1, 1);
+	mii_ethtool_gset(&dev->mii, &ecmd);
+	mode = AX88172_MEDIUM_DEFAULT;
+
+	if (ecmd.duplex != DUPLEX_FULL)
+		mode |= ~AX88172_MEDIUM_FD;
+
+	devdbg(dev, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+	asix_write_medium_mode(dev, mode);
+
+	return 0;
 }
 
 static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -501,6 +825,9 @@
 	void *buf;
 	int i;
 	unsigned long gpio_bits = dev->driver_info->data;
+	struct asix_data *data = (struct asix_data *)&dev->data;
+
+	data->eeprom_len = AX88172_EEPROM_LEN;
 
 	usbnet_get_endpoints(dev,intf);
 
@@ -519,12 +846,12 @@
 		msleep(5);
 	}
 
-	if ((ret = asix_write_rx_ctl(dev,0x80)) < 0)
+	if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0)
 		goto out2;
 
 	/* Get the MAC address */
 	memset(buf, 0, ETH_ALEN);
-	if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+	if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID,
 				0, 0, 6, buf)) < 0) {
 		dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
 		goto out2;
@@ -537,14 +864,14 @@
 	dev->mii.mdio_write = asix_mdio_write;
 	dev->mii.phy_id_mask = 0x3f;
 	dev->mii.reg_num_mask = 0x1f;
-	dev->mii.phy_id = asix_get_phyid(dev);
+	dev->mii.phy_id = asix_get_phy_addr(dev);
 	dev->net->do_ioctl = asix_ioctl;
 
-	dev->net->set_multicast_list = asix_set_multicast;
+	dev->net->set_multicast_list = ax88172_set_multicast;
 	dev->net->ethtool_ops = &ax88172_ethtool_ops;
 
-	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
 		ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
 	mii_nway_restart(&dev->mii);
 
@@ -557,7 +884,8 @@
 
 static struct ethtool_ops ax88772_ethtool_ops = {
 	.get_drvinfo		= asix_get_drvinfo,
-	.get_link		= ethtool_op_get_link,
+	.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,
@@ -568,10 +896,37 @@
 	.set_settings		= asix_set_settings,
 };
 
+static int ax88772_link_reset(struct usbnet *dev)
+{
+	u16 mode;
+	struct ethtool_cmd ecmd;
+
+	mii_check_media(&dev->mii, 1, 1);
+	mii_ethtool_gset(&dev->mii, &ecmd);
+	mode = AX88772_MEDIUM_DEFAULT;
+
+	if (ecmd.speed != SPEED_100)
+		mode &= ~AX_MEDIUM_PS;
+
+	if (ecmd.duplex != DUPLEX_FULL)
+		mode &= ~AX_MEDIUM_FD;
+
+	devdbg(dev, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+	asix_write_medium_mode(dev, mode);
+
+	return 0;
+}
+
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret;
 	void *buf;
+	u16 rx_ctl;
+	struct asix_data *data = (struct asix_data *)&dev->data;
+	u32 phyid;
+
+	data->eeprom_len = AX88772_EEPROM_LEN;
 
 	usbnet_get_endpoints(dev,intf);
 
@@ -582,13 +937,12 @@
 		goto out1;
 	}
 
-	if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
-				     0x00B0, 0, 0, buf)) < 0)
+	if ((ret = asix_write_gpio(dev,
+			AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
 		goto out2;
 
-	msleep(5);
 	if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
-				0x0001, 0, 0, buf)) < 0) {
+				0x0000, 0, 0, buf)) < 0) {
 		dbg("Select PHY #1 failed: %d", ret);
 		goto out2;
 	}
@@ -605,36 +959,34 @@
 		goto out2;
 
 	msleep(150);
-	if ((ret = asix_write_rx_ctl(dev, 0x00)) < 0)
+	rx_ctl = asix_read_rx_ctl(dev);
+	dbg("RX_CTL is 0x%04x after software reset", rx_ctl);
+	if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0)
 		goto out2;
 
+	rx_ctl = asix_read_rx_ctl(dev);
+	dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
+
 	/* Get the MAC address */
 	memset(buf, 0, ETH_ALEN);
-	if ((ret = asix_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+	if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
 				0, 0, ETH_ALEN, buf)) < 0) {
 		dbg("Failed to read MAC address: %d", ret);
 		goto out2;
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-	if ((ret = asix_set_sw_mii(dev)) < 0)
-		goto out2;
-
-	if (((ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG,
-	      			0x0010, 2, 2, buf)) < 0)
-			|| (*((u16 *)buf) != 0x003b)) {
-		dbg("Read PHY register 2 must be 0x3b00: %d", ret);
-		goto out2;
-	}
-
 	/* Initialize MII structure */
 	dev->mii.dev = dev->net;
 	dev->mii.mdio_read = asix_mdio_read;
 	dev->mii.mdio_write = asix_mdio_write;
-	dev->mii.phy_id_mask = 0xff;
-	dev->mii.reg_num_mask = 0xff;
+	dev->mii.phy_id_mask = 0x1f;
+	dev->mii.reg_num_mask = 0x1f;
 	dev->net->do_ioctl = asix_ioctl;
-	dev->mii.phy_id = asix_get_phyid(dev);
+	dev->mii.phy_id = asix_get_phy_addr(dev);
+
+	phyid = asix_get_phyid(dev);
+	dbg("PHYID=0x%08x", phyid);
 
 	if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
 		goto out2;
@@ -649,16 +1001,13 @@
 	dev->net->set_multicast_list = asix_set_multicast;
 	dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
-	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
 			ADVERTISE_ALL | ADVERTISE_CSMA);
 	mii_nway_restart(&dev->mii);
 
-	if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
-				AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
-		dbg("Write medium mode register: %d", ret);
+	if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0)
 		goto out2;
-	}
 
 	if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
 				AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
@@ -666,13 +1015,17 @@
 		dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
 		goto out2;
 	}
-	if ((ret = asix_set_hw_mii(dev)) < 0)
-		goto out2;
 
 	/* Set RX_CTL to default values with 2k buffer, and enable cactus */
-	if ((ret = asix_write_rx_ctl(dev, 0x0088)) < 0)
+	if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
 		goto out2;
 
+	rx_ctl = asix_read_rx_ctl(dev);
+	dbg("RX_CTL is 0x%04x after all initializations", rx_ctl);
+
+	rx_ctl = asix_read_medium_status(dev);
+	dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
+
 	kfree(buf);
 
 	/* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
@@ -690,122 +1043,287 @@
 	return ret;
 }
 
-static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+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,
+};
+
+static int marvell_phy_init(struct usbnet *dev)
 {
-	u8  *head;
-	u32  header;
-	char *packet;
-	struct sk_buff *ax_skb;
-	u16 size;
+	struct asix_data *data = (struct asix_data *)&dev->data;
+	u16 reg;
 
-	head = (u8 *) skb->data;
-	memcpy(&header, head, sizeof(header));
-	le32_to_cpus(&header);
-	packet = head + sizeof(header);
+	devdbg(dev,"marvell_phy_init()");
 
-	skb_pull(skb, 4);
+	reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS);
+	devdbg(dev,"MII_MARVELL_STATUS = 0x%04x", reg);
 
-	while (skb->len > 0) {
-		if ((short)(header & 0x0000ffff) !=
-		    ~((short)((header & 0xffff0000) >> 16))) {
-			devdbg(dev,"header length data is error");
-		}
-		/* get the packet length */
-		size = (u16) (header & 0x0000ffff);
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL,
+			MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY);
 
-		if ((skb->len) - ((size + 1) & 0xfffe) == 0)
-			return 2;
-		if (size > ETH_FRAME_LEN) {
-			devdbg(dev,"invalid rx length %d", size);
-			return 0;
-		}
-		ax_skb = skb_clone(skb, GFP_ATOMIC);
-		if (ax_skb) {
-			ax_skb->len = size;
-			ax_skb->data = packet;
-			ax_skb->tail = packet + size;
-			usbnet_skb_return(dev, ax_skb);
-		} else {
-			return 0;
-		}
+	if (data->ledmode) {
+		reg = asix_mdio_read(dev->net, dev->mii.phy_id,
+			MII_MARVELL_LED_CTRL);
+		devdbg(dev,"MII_MARVELL_LED_CTRL (1) = 0x%04x", reg);
 
-		skb_pull(skb, (size + 1) & 0xfffe);
+		reg &= 0xf8ff;
+		reg |= (1 + 0x0100);
+		asix_mdio_write(dev->net, dev->mii.phy_id,
+			MII_MARVELL_LED_CTRL, reg);
 
-		if (skb->len == 0)
-			break;
-
-		head = (u8 *) skb->data;
-		memcpy(&header, head, sizeof(header));
-		le32_to_cpus(&header);
-		packet = head + sizeof(header);
-		skb_pull(skb, 4);
+		reg = asix_mdio_read(dev->net, dev->mii.phy_id,
+			MII_MARVELL_LED_CTRL);
+		devdbg(dev,"MII_MARVELL_LED_CTRL (2) = 0x%04x", reg);
+		reg &= 0xfc0f;
 	}
 
-	if (skb->len < 0) {
-		devdbg(dev,"invalid rx length %d", skb->len);
-		return 0;
-	}
-	return 1;
-}
-
-static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-					gfp_t flags)
-{
-	int padlen;
-	int headroom = skb_headroom(skb);
-	int tailroom = skb_tailroom(skb);
-	u32 packet_len;
-	u32 padbytes = 0xffff0000;
-
-	padlen = ((skb->len + 4) % 512) ? 0 : 4;
-
-	if ((!skb_cloned(skb))
-	    && ((headroom + tailroom) >= (4 + padlen))) {
-		if ((headroom < 4) || (tailroom < padlen)) {
-			skb->data = memmove(skb->head + 4, skb->data, skb->len);
-			skb->tail = skb->data + skb->len;
-		}
-	} else {
-		struct sk_buff *skb2;
-		skb2 = skb_copy_expand(skb, 4, padlen, flags);
-		dev_kfree_skb_any(skb);
-		skb = skb2;
-		if (!skb)
-			return NULL;
-	}
-
-	skb_push(skb, 4);
-	packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
-	memcpy(skb->data, &packet_len, sizeof(packet_len));
-
-	if ((skb->len % 512) == 0) {
-		memcpy( skb->tail, &padbytes, sizeof(padbytes));
-		skb_put(skb, sizeof(padbytes));
-	}
-	return skb;
-}
-
-static int ax88772_link_reset(struct usbnet *dev)
-{
-	u16 lpa;
-	u16 adv;
-	u16 res;
-	u16 mode;
-
-	mode = AX88772_MEDIUM_DEFAULT;
-	lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-	adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
-	res = mii_nway_result(lpa|adv);
-
-	if ((res & LPA_DUPLEX) == 0)
-		mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
-	if ((res & LPA_100) == 0)
-		mode &= ~AX88772_MEDIUM_100MB;
-	asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
-
 	return 0;
 }
 
+static int marvell_led_status(struct usbnet *dev, u16 speed)
+{
+	u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL);
+
+	devdbg(dev, "marvell_led_status() read 0x%04x", reg);
+
+	/* Clear out the center LED bits - 0x03F0 */
+	reg &= 0xfc0f;
+
+	switch (speed) {
+		case SPEED_1000:
+			reg |= 0x03e0;
+			break;
+		case SPEED_100:
+			reg |= 0x03b0;
+			break;
+		default:
+			reg |= 0x02f0;
+	}
+
+	devdbg(dev, "marvell_led_status() writing 0x%04x", reg);
+	asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg);
+
+	return 0;
+}
+
+static int ax88178_link_reset(struct usbnet *dev)
+{
+	u16 mode;
+	struct ethtool_cmd ecmd;
+	struct asix_data *data = (struct asix_data *)&dev->data;
+
+	devdbg(dev,"ax88178_link_reset()");
+
+	mii_check_media(&dev->mii, 1, 1);
+	mii_ethtool_gset(&dev->mii, &ecmd);
+	mode = AX88178_MEDIUM_DEFAULT;
+
+	if (ecmd.speed == SPEED_1000)
+		mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
+	else if (ecmd.speed == SPEED_100)
+		mode |= AX_MEDIUM_PS;
+	else
+		mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
+
+	if (ecmd.duplex == DUPLEX_FULL)
+		mode |= AX_MEDIUM_FD;
+	else
+		mode &= ~AX_MEDIUM_FD;
+
+	devdbg(dev, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+	asix_write_medium_mode(dev, mode);
+
+	if (data->phymode == PHY_MODE_MARVELL && data->ledmode)
+		marvell_led_status(dev, ecmd.speed);
+
+	return 0;
+}
+
+static void ax88178_set_mfb(struct usbnet *dev)
+{
+	u16 mfb = AX_RX_CTL_MFB_16384;
+	u16 rxctl;
+	u16 medium;
+	int old_rx_urb_size = dev->rx_urb_size;
+
+	if (dev->hard_mtu < 2048) {
+		dev->rx_urb_size = 2048;
+		mfb = AX_RX_CTL_MFB_2048;
+	} else if (dev->hard_mtu < 4096) {
+		dev->rx_urb_size = 4096;
+		mfb = AX_RX_CTL_MFB_4096;
+	} else if (dev->hard_mtu < 8192) {
+		dev->rx_urb_size = 8192;
+		mfb = AX_RX_CTL_MFB_8192;
+	} else if (dev->hard_mtu < 16384) {
+		dev->rx_urb_size = 16384;
+		mfb = AX_RX_CTL_MFB_16384;
+	}
+
+	rxctl = asix_read_rx_ctl(dev);
+	asix_write_rx_ctl(dev, (rxctl & ~AX_RX_CTL_MFB_16384) | mfb);
+
+	medium = asix_read_medium_status(dev);
+	if (dev->net->mtu > 1500)
+		medium |= AX_MEDIUM_JFE;
+	else
+		medium &= ~AX_MEDIUM_JFE;
+	asix_write_medium_mode(dev, medium);
+
+	if (dev->rx_urb_size > old_rx_urb_size)
+		usbnet_unlink_rx_urbs(dev);
+}
+
+static int ax88178_change_mtu(struct net_device *net, int new_mtu)
+{
+	struct usbnet *dev = netdev_priv(net);
+	int ll_mtu = new_mtu + net->hard_header_len + 4;
+
+	devdbg(dev, "ax88178_change_mtu() new_mtu=%d", new_mtu);
+
+	if (new_mtu <= 0 || ll_mtu > 16384)
+		return -EINVAL;
+
+	if ((ll_mtu % dev->maxpacket) == 0)
+		return -EDOM;
+
+	net->mtu = new_mtu;
+	dev->hard_mtu = net->mtu + net->hard_header_len;
+	ax88178_set_mfb(dev);
+
+	return 0;
+}
+
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct asix_data *data = (struct asix_data *)&dev->data;
+	int ret;
+	void *buf;
+	u16 eeprom;
+	int gpio0 = 0;
+	u32 phyid;
+
+	usbnet_get_endpoints(dev,intf);
+
+	buf = kmalloc(6, GFP_KERNEL);
+	if(!buf) {
+		dbg ("Cannot allocate memory for buffer");
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	eeprom = 0;
+	asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &eeprom);
+	dbg("GPIO Status: 0x%04x", eeprom);
+
+	asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
+	asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
+	asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
+
+	dbg("EEPROM index 0x17 is 0x%04x", eeprom);
+
+	if (eeprom == 0xffff) {
+		data->phymode = PHY_MODE_MARVELL;
+		data->ledmode = 0;
+		gpio0 = 1;
+	} else {
+		data->phymode = eeprom & 7;
+		data->ledmode = eeprom >> 8;
+		gpio0 = (eeprom & 0x80) ? 0 : 1;
+	}
+	dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
+
+	asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
+	if ((eeprom >> 8) != 1) {
+		asix_write_gpio(dev, 0x003c, 30);
+		asix_write_gpio(dev, 0x001c, 300);
+		asix_write_gpio(dev, 0x003c, 30);
+	} else {
+		dbg("gpio phymode == 1 path");
+		asix_write_gpio(dev, AX_GPIO_GPO1EN, 30);
+		asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
+	}
+
+	asix_sw_reset(dev, 0);
+	msleep(150);
+
+	asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
+	msleep(150);
+
+	asix_write_rx_ctl(dev, 0);
+
+	/* Get the MAC address */
+	memset(buf, 0, ETH_ALEN);
+	if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+				0, 0, ETH_ALEN, buf)) < 0) {
+		dbg("Failed to read MAC address: %d", ret);
+		goto out2;
+	}
+	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+	/* Initialize MII structure */
+	dev->mii.dev = dev->net;
+	dev->mii.mdio_read = asix_mdio_read;
+	dev->mii.mdio_write = asix_mdio_write;
+	dev->mii.phy_id_mask = 0x1f;
+	dev->mii.reg_num_mask = 0xff;
+	dev->mii.supports_gmii = 1;
+	dev->net->do_ioctl = asix_ioctl;
+	dev->mii.phy_id = asix_get_phy_addr(dev);
+	dev->net->set_multicast_list = asix_set_multicast;
+	dev->net->ethtool_ops = &ax88178_ethtool_ops;
+	dev->net->change_mtu = &ax88178_change_mtu;
+
+	phyid = asix_get_phyid(dev);
+	dbg("PHYID=0x%08x", phyid);
+
+	if (data->phymode == PHY_MODE_MARVELL) {
+		marvell_phy_init(dev);
+		msleep(60);
+	}
+
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+			BMCR_RESET | BMCR_ANENABLE);
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+			ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+	asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
+			ADVERTISE_1000FULL);
+
+	mii_nway_restart(&dev->mii);
+
+	if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0)
+		goto out2;
+
+	if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
+		goto out2;
+
+	kfree(buf);
+
+	/* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
+	if (dev->driver_info->flags & FLAG_FRAMING_AX) {
+		/* hard_mtu  is still the default - the device does not support
+		   jumbo eth frames */
+		dev->rx_urb_size = 2048;
+	}
+
+	return 0;
+
+out2:
+	kfree(buf);
+out1:
+	return ret;
+}
+
 static const struct driver_info ax8817x_info = {
 	.description = "ASIX AX8817x USB 2.0 Ethernet",
 	.bind = ax88172_bind,
@@ -853,8 +1371,19 @@
 	.link_reset = ax88772_link_reset,
 	.reset = ax88772_link_reset,
 	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
-	.rx_fixup = ax88772_rx_fixup,
-	.tx_fixup = ax88772_tx_fixup,
+	.rx_fixup = asix_rx_fixup,
+	.tx_fixup = asix_tx_fixup,
+};
+
+static const struct driver_info ax88178_info = {
+	.description = "ASIX AX88178 USB 2.0 Ethernet",
+	.bind = ax88178_bind,
+	.status = asix_status,
+	.link_reset = ax88178_link_reset,
+	.reset = ax88178_link_reset,
+	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
+	.rx_fixup = asix_rx_fixup,
+	.tx_fixup = asix_tx_fixup,
 };
 
 static const struct usb_device_id	products [] = {
@@ -913,7 +1442,7 @@
 }, {
 	// ASIX AX88178 10/100/1000
 	USB_DEVICE (0x0b95, 0x1780),
-	.driver_info = (unsigned long) &ax88772_info,
+	.driver_info = (unsigned long) &ax88178_info,
 }, {
 	// Linksys USB200M Rev 2
 	USB_DEVICE (0x13b1, 0x0018),
@@ -922,6 +1451,18 @@
 	// 0Q0 cable ethernet
 	USB_DEVICE (0x1557, 0x7720),
 	.driver_info = (unsigned long) &ax88772_info,
+}, {
+	// DLink DUB-E100 H/W Ver B1
+	USB_DEVICE (0x07d1, 0x3c05),
+	.driver_info = (unsigned long) &ax88772_info,
+}, {
+	// DLink DUB-E100 H/W Ver B1 Alternate
+	USB_DEVICE (0x2001, 0x3c05),
+	.driver_info = (unsigned long) &ax88772_info,
+}, {
+	// Linksys USB1000
+	USB_DEVICE (0x1737, 0x0039),
+	.driver_info = (unsigned long) &ax88178_info,
 },
 	{ },		// END
 };
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index def3bb8..544d41f 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -165,6 +165,7 @@
 	{ USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */
 	{ USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */
 	{ USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */
+	{ USB_DEVICE(0x1668, 0x0323) }, /* Actiontec USB Ethernet */
 	{ USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
 	{} /* Null terminator */
 };
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index a9b6eea..301baa7 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -498,25 +498,24 @@
 static struct sk_buff *
 net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
-	int			padlen;
 	struct sk_buff		*skb2;
 	struct nc_header	*header = NULL;
 	struct nc_trailer	*trailer = NULL;
+	int			padlen = sizeof (struct nc_trailer);
 	int			len = skb->len;
 
-	padlen = ((len + sizeof (struct nc_header)
-			+ sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+	if (!((len + padlen + sizeof (struct nc_header)) & 0x01))
+		padlen++;
 	if (!skb_cloned(skb)) {
 		int	headroom = skb_headroom(skb);
 		int	tailroom = skb_tailroom(skb);
 
-		if ((padlen + sizeof (struct nc_trailer)) <= tailroom
-			    && sizeof (struct nc_header) <= headroom)
+		if (padlen <= tailroom &&
+		    sizeof(struct nc_header) <= headroom)
 			/* There's enough head and tail room */
 			goto encapsulate;
 
-		if ((sizeof (struct nc_header) + padlen
-					+ sizeof (struct nc_trailer)) <
+		if ((sizeof (struct nc_header) + padlen) <
 				(headroom + tailroom)) {
 			/* There's enough total room, so just readjust */
 			skb->data = memmove(skb->head
@@ -530,7 +529,7 @@
 	/* Create a new skb to use with the correct size */
 	skb2 = skb_copy_expand(skb,
 				sizeof (struct nc_header),
-				sizeof (struct nc_trailer) + padlen,
+				padlen,
 				flags);
 	dev_kfree_skb_any(skb);
 	if (!skb2)
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index ab21f96..918cf5a 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -45,7 +45,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.6.13 (2005/11/13)"
+#define DRIVER_VERSION "v0.6.14 (2006/09/27)"
 #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -339,7 +339,7 @@
 	}
 fail:
 	if (netif_msg_drv(pegasus))
-		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+		dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
 
 	return ret;
 }
@@ -376,7 +376,7 @@
 
 fail:
 	if (netif_msg_drv(pegasus))
-		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+		dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
 	return -ETIMEDOUT;
 }
 
@@ -413,7 +413,7 @@
 
 fail:
 	if (netif_msg_drv(pegasus))
-		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+		dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
 	return -ETIMEDOUT;
 }
 
@@ -461,7 +461,7 @@
 		return ret;
 fail:
 	if (netif_msg_drv(pegasus))
-		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+		dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
 	return -ETIMEDOUT;
 }
 #endif				/* PEGASUS_WRITE_EEPROM */
@@ -481,8 +481,12 @@
 {
 	__u8 node_id[6];
 
-	get_node_id(pegasus, node_id);
-	set_registers(pegasus, EthID, sizeof (node_id), node_id);
+	if (pegasus->features & PEGASUS_II) {
+		get_registers(pegasus, 0x10, sizeof(node_id), node_id);
+	} else {
+		get_node_id(pegasus, node_id);
+		set_registers(pegasus, EthID, sizeof (node_id), node_id);
+	}
 	memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
 }
 
@@ -619,7 +623,7 @@
 	switch (urb->status) {
 	case 0:
 		break;
-	case -ETIMEDOUT:
+	case -ETIME:
 		if (netif_msg_rx_err(pegasus))
 			pr_debug("%s: reset MAC\n", net->name);
 		pegasus->flags &= ~PEGASUS_RX_BUSY;
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index a72685b..2364c20 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -438,7 +438,7 @@
 		break;
 	case -ENOENT:
 		return;	/* the urb is in unlink state */
-	case -ETIMEDOUT:
+	case -ETIME:
 		warn("may be reset is needed?..");
 		goto goon;
 	default:
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 54183e1..98a522f 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -61,8 +61,11 @@
  * let the USB host controller be busy for 5msec or more before an irq
  * is required, under load.  Jumbograms change the equation.
  */
-#define	RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
-#define	TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
+#define RX_MAX_QUEUE_MEMORY (60 * 1518)
+#define	RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+			(RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
+#define	TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+			(RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
 
 // reawaken network queue this soon after stopping; else watchdog barks
 #define TX_TIMEOUT_JIFFIES	(5*HZ)
@@ -227,13 +230,23 @@
 {
 	struct usbnet	*dev = netdev_priv(net);
 	int		ll_mtu = new_mtu + net->hard_header_len;
+	int		old_hard_mtu = dev->hard_mtu;
+	int		old_rx_urb_size = dev->rx_urb_size;
 
-	if (new_mtu <= 0 || ll_mtu > dev->hard_mtu)
+	if (new_mtu <= 0)
 		return -EINVAL;
 	// no second zero-length packet read wanted after mtu-sized packets
 	if ((ll_mtu % dev->maxpacket) == 0)
 		return -EDOM;
 	net->mtu = new_mtu;
+
+	dev->hard_mtu = net->mtu + net->hard_header_len;
+	if (dev->rx_urb_size == old_hard_mtu) {
+		dev->rx_urb_size = dev->hard_mtu;
+		if (dev->rx_urb_size > old_rx_urb_size)
+			usbnet_unlink_rx_urbs(dev);
+	}
+
 	return 0;
 }
 
@@ -412,9 +425,9 @@
 	    // we get controller i/o faults during khubd disconnect() delays.
 	    // throttle down resubmits, to avoid log floods; just temporarily,
 	    // so we still recover when the fault isn't a khubd delay.
-	    case -EPROTO:		// ehci
-	    case -ETIMEDOUT:		// ohci
-	    case -EILSEQ:		// uhci
+	    case -EPROTO:
+	    case -ETIME:
+	    case -EILSEQ:
 		dev->stats.rx_errors++;
 		if (!timer_pending (&dev->delay)) {
 			mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -521,6 +534,17 @@
 	return count;
 }
 
+// Flush all pending rx urbs
+// minidrivers may need to do this when the MTU changes
+
+void usbnet_unlink_rx_urbs(struct usbnet *dev)
+{
+	if (netif_running(dev->net)) {
+		(void) unlink_urbs (dev, &dev->rxq);
+		tasklet_schedule(&dev->bh);
+	}
+}
+EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
 
 /*-------------------------------------------------------------------------*/
 
@@ -629,7 +653,7 @@
 
 		devinfo (dev, "open: enable queueing "
 				"(rx %d, tx %d) mtu %d %s framing",
-			RX_QLEN (dev), TX_QLEN (dev), dev->net->mtu,
+			(int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu,
 			framing);
 	}
 
@@ -797,9 +821,9 @@
 
 		// like rx, tx gets controller i/o faults during khubd delays
 		// and so it uses the same throttling mechanism.
-		case -EPROTO:		// ehci
-		case -ETIMEDOUT:	// ohci
-		case -EILSEQ:		// uhci
+		case -EPROTO:
+		case -ETIME:
+		case -EILSEQ:
 			if (!timer_pending (&dev->delay)) {
 				mod_timer (&dev->delay,
 					jiffies + THROTTLE_JIFFIES);
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h
index 89fc495..c0746f0 100644
--- a/drivers/usb/net/usbnet.h
+++ b/drivers/usb/net/usbnet.h
@@ -166,6 +166,7 @@
 extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *);
 extern void usbnet_defer_kevent (struct usbnet *, int);
 extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
+extern void usbnet_unlink_rx_urbs(struct usbnet *);
 
 extern u32 usbnet_get_msglevel (struct net_device *);
 extern void usbnet_set_msglevel (struct net_device *, u32);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index f5b9438..5076b9d 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -53,6 +53,15 @@
 	  support" be compiled as a module for this driver to be used
 	  properly.
 
+config USB_SERIAL_AIRCABLE
+	tristate "AIRcable USB Bluetooth Dongle Driver (EXPERIMENTAL)"
+	depends on USB_SERIAL && EXPERIMENTAL
+	help
+	    Say Y here if you want to use AIRcable USB Bluetoot Dongle.
+
+	    To compile this driver as a module, choose M here: the module
+	    will be called aircable.
+
 config USB_SERIAL_AIRPRIME
 	tristate "USB AirPrime CDMA Wireless Driver"
 	depends on USB_SERIAL
@@ -413,6 +422,21 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called mct_u232.
 
+config USB_SERIAL_MOS7840
+	tristate "USB Moschip 7840/7820 USB Serial Driver"
+	depends on USB_SERIAL
+	---help---
+	  Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820
+	  Dual-Serial port device from MosChip Semiconductor.
+
+	  The MCS7840 and MCS7820 have been developed to connect a wide range
+	  of standard serial devices to a USB host.  The MCS7840 has a USB
+	  device controller connected to four (4) individual UARTs while the
+	  MCS7820 controller connects to two (2) individual UARTs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mos7840.  If unsure, choose N.
+
 config USB_SERIAL_NAVMAN
 	tristate "USB Navman GPS device"
 	depends on USB_SERIAL
@@ -526,5 +550,6 @@
 	depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
 	default y
 
+
 endmenu
 
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 8efed2c..8dce833 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -11,6 +11,7 @@
 
 usbserial-objs	:= usb-serial.o generic.o bus.o $(usbserial-obj-y)
 
+obj-$(CONFIG_USB_SERIAL_AIRCABLE)		+= aircable.o
 obj-$(CONFIG_USB_SERIAL_AIRPRIME)		+= airprime.o
 obj-$(CONFIG_USB_SERIAL_ARK3116)		+= ark3116.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)			+= belkin_sa.o
@@ -33,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_MOS7840)		+= mos7840.o
 obj-$(CONFIG_USB_SERIAL_NAVMAN)			+= navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)		+= omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)			+= option.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
new file mode 100644
index 0000000..2ccd9de
--- /dev/null
+++ b/drivers/usb/serial/aircable.c
@@ -0,0 +1,625 @@
+/*
+ * AIRcable USB Bluetooth Dongle Driver.
+ *
+ * Copyright (C) 2006 Manuel Francisco Naranjo (naranjo.manuel@gmail.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.
+ *
+ * The device works as an standard CDC device, it has 2 interfaces, the first
+ * one is for firmware access and the second is the serial one.
+ * The protocol is very simply, there are two posibilities reading or writing.
+ * When writting the first urb must have a Header that starts with 0x20 0x29 the
+ * next two bytes must say how much data will be sended.
+ * When reading the process is almost equal except that the header starts with
+ * 0x00 0x20.
+ *
+ * The device simply need some stuff to understand data comming from the usb
+ * buffer: The First and Second byte is used for a Header, the Third and Fourth
+ * tells the  device the amount of information the package holds.
+ * Packages are 60 bytes long Header Stuff.
+ * When writting to the device the first two bytes of the header are 0x20 0x29
+ * When reading the bytes are 0x00 0x20, or 0x00 0x10, there is an strange
+ * situation, when too much data arrives to the device because it sends the data
+ * but with out the header. I will use a simply hack to override this situation,
+ * if there is data coming that does not contain any header, then that is data
+ * that must go directly to the tty, as there is no documentation about if there
+ * is any other control code, I will simply check for the first
+ * one.
+ *
+ * The driver registers himself with the USB-serial core and the USB Core. I had
+ * to implement a probe function agains USB-serial, because other way, the
+ * driver was attaching himself to both interfaces. I have tryed with different
+ * configurations of usb_serial_driver with out exit, only the probe function
+ * could handle this correctly.
+ *
+ * I have taken some info from a Greg Kroah-Hartman article:
+ * http://www.linuxjournal.com/article/6573
+ * And from Linux Device Driver Kit CD, which is a great work, the authors taken
+ * the work to recompile lots of information an knowladge in drivers development
+ * and made it all avaible inside a cd.
+ * URL: http://kernel.org/pub/linux/kernel/people/gregkh/ddk/
+ *
+ */
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/circ_buf.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static int debug;
+
+/* Vendor and Product ID */
+#define AIRCABLE_VID		0x16CA
+#define AIRCABLE_USB_PID	0x1502
+
+/* write buffer size defines */
+#define AIRCABLE_BUF_SIZE	2048
+
+/* Protocol Stuff */
+#define HCI_HEADER_LENGTH	0x4
+#define TX_HEADER_0		0x20
+#define TX_HEADER_1		0x29
+#define RX_HEADER_0		0x00
+#define RX_HEADER_1		0x20
+#define MAX_HCI_FRAMESIZE	60
+#define HCI_COMPLETE_FRAME	64
+
+/* rx_flags */
+#define THROTTLED		0x01
+#define ACTUALLY_THROTTLED	0x02
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0b2"
+#define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>"
+#define DRIVER_DESC "AIRcable USB Driver"
+
+/* ID table that will be registered with USB core */
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+
+/* Internal Structure */
+struct aircable_private {
+	spinlock_t rx_lock;		/* spinlock for the receive lines */
+	struct circ_buf *tx_buf;	/* write buffer */
+	struct circ_buf *rx_buf;	/* read buffer */
+	int rx_flags;			/* for throttilng */
+	struct work_struct rx_work;	/* work cue for the receiving line */
+};
+
+/* Private methods */
+
+/* Circular Buffer Methods, code from ti_usb_3410_5052 used */
+/*
+ * serial_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void serial_buf_clear(struct circ_buf *cb)
+{
+	cb->head = cb->tail = 0;
+}
+
+/*
+ * serial_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct circ_buf *serial_buf_alloc(void)
+{
+	struct circ_buf *cb;
+	cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+	if (cb == NULL)
+		return NULL;
+	cb->buf = kmalloc(AIRCABLE_BUF_SIZE, GFP_KERNEL);
+	if (cb->buf == NULL) {
+		kfree(cb);
+		return NULL;
+	}
+	serial_buf_clear(cb);
+	return cb;
+}
+
+/*
+ * serial_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void serial_buf_free(struct circ_buf *cb)
+{
+	kfree(cb->buf);
+	kfree(cb);
+}
+
+/*
+ * serial_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static int serial_buf_data_avail(struct circ_buf *cb)
+{
+	return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE);
+}
+
+/*
+ * serial_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static int serial_buf_put(struct circ_buf *cb, const char *buf, int count)
+{
+	int c, ret = 0;
+	while (1) {
+		c = CIRC_SPACE_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
+		if (count < c)
+			c = count;
+		if (c <= 0)
+			break;
+		memcpy(cb->buf + cb->head, buf, c);
+		cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1);
+		buf += c;
+		count -= c;
+		ret= c;
+	}
+	return ret;
+}
+
+/*
+ * serial_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static int serial_buf_get(struct circ_buf *cb, char *buf, int count)
+{
+	int c, ret = 0;
+	while (1) {
+		c = CIRC_CNT_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
+		if (count < c)
+			c = count;
+		if (c <= 0)
+			break;
+		memcpy(buf, cb->buf + cb->tail, c);
+		cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1);
+		buf += c;
+		count -= c;
+		ret= c;
+	}
+	return ret;
+}
+
+/* End of circula buffer methods */
+
+static void aircable_send(struct usb_serial_port *port)
+{
+	int count, result;
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+	unsigned char* buf;
+	dbg("%s - port %d", __FUNCTION__, port->number);
+	if (port->write_urb_busy)
+		return;
+
+	count = min(serial_buf_data_avail(priv->tx_buf), MAX_HCI_FRAMESIZE);
+	if (count == 0)
+		return;
+
+	buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC);
+	if (!buf) {
+		err("%s- kzalloc(%d) failed.", __FUNCTION__,
+		    count + HCI_HEADER_LENGTH);
+		return;
+	}
+
+	buf[0] = TX_HEADER_0;
+	buf[1] = TX_HEADER_1;
+	buf[2] = (unsigned char)count;
+	buf[3] = (unsigned char)(count >> 8);
+	serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
+
+	memcpy(port->write_urb->transfer_buffer, buf,
+	       count + HCI_HEADER_LENGTH);
+
+	kfree(buf);
+	port->write_urb_busy = 1;
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+			      count + HCI_HEADER_LENGTH,
+			      port->write_urb->transfer_buffer);
+	port->write_urb->transfer_buffer_length = count + HCI_HEADER_LENGTH;
+	port->write_urb->dev = port->serial->dev;
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+
+	if (result) {
+		dev_err(&port->dev,
+			"%s - failed submitting write urb, error %d\n",
+			__FUNCTION__, result);
+		port->write_urb_busy = 0;
+	}
+
+	schedule_work(&port->work);
+}
+
+static void aircable_read(void *params)
+{
+	struct usb_serial_port *port = params;
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	unsigned char *data;
+	int count;
+	if (priv->rx_flags & THROTTLED){
+		if (priv->rx_flags & ACTUALLY_THROTTLED)
+			schedule_work(&priv->rx_work);
+		return;
+	}
+
+	/* By now I will flush data to the tty in packages of no more than
+	 * 64 bytes, to ensure I do not get throttled.
+	 * Ask USB mailing list for better aproach.
+	 */
+	tty = port->tty;
+
+	if (!tty)
+		schedule_work(&priv->rx_work);
+
+	count = min(64, serial_buf_data_avail(priv->rx_buf));
+
+	if (count <= 0)
+		return; //We have finished sending everything.
+
+	tty_prepare_flip_string(tty, &data, count);
+	if (!data){
+		err("%s- kzalloc(%d) failed.", __FUNCTION__, count);
+		return;
+	}
+
+	serial_buf_get(priv->rx_buf, data, count);
+
+	tty_flip_buffer_push(tty);
+
+	if (serial_buf_data_avail(priv->rx_buf))
+		schedule_work(&priv->rx_work);
+
+	return;
+}
+/* End of private methods */
+
+static int aircable_probe(struct usb_serial *serial,
+			  const struct usb_device_id *id)
+{
+	struct usb_host_interface *iface_desc = serial->interface->cur_altsetting;
+	struct usb_endpoint_descriptor *endpoint;
+	int num_bulk_out=0;
+	int i;
+
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+		endpoint = &iface_desc->endpoint[i].desc;
+		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+			((endpoint->bmAttributes & 3) == 0x02)) {
+			/* we found our bulk out endpoint */
+			dbg("found bulk out on endpoint %d", i);
+			++num_bulk_out;
+		}
+	}
+
+	if (num_bulk_out == 0) {
+		dbg("Invalid interface, discarding");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int aircable_attach (struct usb_serial *serial)
+{
+	struct usb_serial_port *port = serial->port[0];
+	struct aircable_private *priv;
+
+	priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
+	if (!priv){
+		err("%s- kmalloc(%Zd) failed.", __FUNCTION__,
+			sizeof(struct aircable_private));
+		return -ENOMEM;
+	}
+
+	/* Allocation of Circular Buffers */
+	priv->tx_buf = serial_buf_alloc();
+	if (priv->tx_buf == NULL) {
+		kfree(priv);
+		return -ENOMEM;
+	}
+
+	priv->rx_buf = serial_buf_alloc();
+	if (priv->rx_buf == NULL) {
+		kfree(priv->tx_buf);
+		kfree(priv);
+		return -ENOMEM;
+	}
+
+	priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
+	INIT_WORK(&priv->rx_work, aircable_read, port);
+
+	usb_set_serial_port_data(serial->port[0], priv);
+
+	return 0;
+}
+
+static void aircable_shutdown(struct usb_serial *serial)
+{
+
+	struct usb_serial_port *port = serial->port[0];
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+
+	dbg("%s", __FUNCTION__);
+
+	if (priv) {
+		serial_buf_free(priv->tx_buf);
+		serial_buf_free(priv->rx_buf);
+		usb_set_serial_port_data(port, NULL);
+		kfree(priv);
+	}
+}
+
+static int aircable_write_room(struct usb_serial_port *port)
+{
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+	return serial_buf_data_avail(priv->tx_buf);
+}
+
+static int aircable_write(struct usb_serial_port *port,
+			  const unsigned char *source, int count)
+{
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+	int temp;
+
+	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
+
+	if (!count){
+		dbg("%s - write request of 0 bytes", __FUNCTION__);
+		return count;
+	}
+
+	temp = serial_buf_put(priv->tx_buf, source, count);
+
+	aircable_send(port);
+
+	if (count > AIRCABLE_BUF_SIZE)
+		count = AIRCABLE_BUF_SIZE;
+
+	return count;
+
+}
+
+static void aircable_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_serial_port *port = urb->context;
+	int result;
+
+	dbg("%s - urb->status: %d", __FUNCTION__ , urb->status);
+
+	/* This has been taken from cypress_m8.c cypress_write_int_callback */
+	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);
+			port->write_urb_busy = 0;
+			return;
+		default:
+			/* error in the urb, so we have to resubmit it */
+			dbg("%s - Overflow in write", __FUNCTION__);
+			dbg("%s - nonzero write bulk status received: %d",
+			    __FUNCTION__, urb->status);
+			port->write_urb->transfer_buffer_length = 1;
+			port->write_urb->dev = port->serial->dev;
+			result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+			if (result)
+				dev_err(&urb->dev->dev,
+					"%s - failed resubmitting write urb, error %d\n",
+					__FUNCTION__, result);
+			else
+				return;
+	}
+
+	port->write_urb_busy = 0;
+
+	aircable_send(port);
+}
+
+static void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_serial_port *port = urb->context;
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
+	unsigned long no_packages, remaining, package_length, i;
+	int result, shift = 0;
+	unsigned char *temp;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (urb->status) {
+		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+		if (!port->open_count) {
+			dbg("%s - port is closed, exiting.", __FUNCTION__);
+			return;
+		}
+		if (urb->status == -EPROTO) {
+			dbg("%s - caught -EPROTO, resubmitting the urb",
+			    __FUNCTION__);
+			usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+					  usb_rcvbulkpipe(port->serial->dev,
+					  		  port->bulk_in_endpointAddress),
+					  port->read_urb->transfer_buffer,
+					  port->read_urb->transfer_buffer_length,
+					  aircable_read_bulk_callback, port);
+
+			result = usb_submit_urb(urb, GFP_ATOMIC);
+			if (result)
+				dev_err(&urb->dev->dev,
+					"%s - failed resubmitting read urb, error %d\n",
+					__FUNCTION__, result);
+			return;
+		}
+		dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
+		return;
+	}
+
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+				urb->actual_length,urb->transfer_buffer);
+
+	tty = port->tty;
+	if (tty && urb->actual_length) {
+		if (urb->actual_length <= 2) {
+			/* This is an incomplete package */
+			serial_buf_put(priv->rx_buf, urb->transfer_buffer,
+				       urb->actual_length);
+		} else {
+			temp = urb->transfer_buffer;
+			if (temp[0] == RX_HEADER_0)
+				shift = HCI_HEADER_LENGTH;
+
+			remaining = urb->actual_length;
+			no_packages = urb->actual_length / (HCI_COMPLETE_FRAME);
+
+			if (urb->actual_length % HCI_COMPLETE_FRAME != 0)
+				no_packages+=1;
+
+			for (i = 0; i < no_packages ;i++) {
+				if (remaining > (HCI_COMPLETE_FRAME))
+					package_length = HCI_COMPLETE_FRAME;
+				else
+					package_length = remaining;
+				remaining -= package_length;
+
+				serial_buf_put(priv->rx_buf,
+					urb->transfer_buffer + shift +
+					(HCI_COMPLETE_FRAME) * (i),
+					package_length - shift);
+			}
+		}
+		aircable_read(port);
+	}
+
+	/* Schedule the next read _if_ we are still open */
+	if (port->open_count) {
+		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+				  usb_rcvbulkpipe(port->serial->dev,
+				  		  port->bulk_in_endpointAddress),
+				  port->read_urb->transfer_buffer,
+				  port->read_urb->transfer_buffer_length,
+				  aircable_read_bulk_callback, port);
+
+		result = usb_submit_urb(urb, GFP_ATOMIC);
+		if (result)
+			dev_err(&urb->dev->dev,
+				"%s - failed resubmitting read urb, error %d\n",
+				__FUNCTION__, result);
+	}
+
+	return;
+}
+
+/* Based on ftdi_sio.c throttle */
+static void aircable_throttle(struct usb_serial_port *port)
+{
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->rx_lock, flags);
+	priv->rx_flags |= THROTTLED;
+	spin_unlock_irqrestore(&priv->rx_lock, flags);
+}
+
+/* Based on ftdi_sio.c unthrottle */
+static void aircable_unthrottle(struct usb_serial_port *port)
+{
+	struct aircable_private *priv = usb_get_serial_port_data(port);
+	int actually_throttled;
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->rx_lock, flags);
+	actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+	priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
+	spin_unlock_irqrestore(&priv->rx_lock, flags);
+
+	if (actually_throttled)
+		schedule_work(&priv->rx_work);
+}
+
+static struct usb_serial_driver aircable_device = {
+	.description =		"aircable",
+	.id_table = 		id_table,
+	.num_ports =		1,
+	.attach =		aircable_attach,
+	.probe =		aircable_probe,
+	.shutdown =		aircable_shutdown,
+	.write =		aircable_write,
+	.write_room =		aircable_write_room,
+	.write_bulk_callback =	aircable_write_bulk_callback,
+	.read_bulk_callback =	aircable_read_bulk_callback,
+	.throttle =		aircable_throttle,
+	.unthrottle =		aircable_unthrottle,
+};
+
+static struct usb_driver aircable_driver = {
+	.name =		"aircable",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
+static int __init aircable_init (void)
+{
+	int retval;
+	retval = usb_serial_register(&aircable_device);
+	if (retval)
+		goto failed_serial_register;
+	retval = usb_register(&aircable_driver);
+	if (retval)
+		goto failed_usb_register;
+	return 0;
+
+failed_serial_register:
+	usb_serial_deregister(&aircable_device);
+failed_usb_register:
+	return retval;
+}
+
+static void __exit aircable_exit (void)
+{
+	usb_deregister(&aircable_driver);
+	usb_serial_deregister(&aircable_device);
+}
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_init(aircable_init);
+module_exit(aircable_exit);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 6208253..6e1a84a 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -1,7 +1,7 @@
 /*
  * AirPrime CDMA Wireless Serial USB driver
  *
- * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ * 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
@@ -11,26 +11,264 @@
 #include <linux/kernel.h>
 #include <linux/init.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(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
-	{ USB_DEVICE(0xf3d, 0x0112) },  /* AirPrime CDMA Wireless PC Card */
-	{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+	{ 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 */
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
+#define URB_TRANSFER_BUFFER_SIZE	4096
+#define NUM_READ_URBS			4
+#define NUM_WRITE_URBS			4
+#define NUM_BULK_EPS			3
+#define MAX_BULK_EPS			6
+
+/* if overridden by the user, then use their value for the size of the
+ * read and write urbs, and the number of endpoints */
+static int buffer_size = URB_TRANSFER_BUFFER_SIZE;
+static int endpoints = NUM_BULK_EPS;
+static int debug;
+struct airprime_private {
+	spinlock_t lock;
+	int outstanding_urbs;
+	int throttled;
+	struct urb *read_urbp[NUM_READ_URBS];
+};
+
+static void airprime_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_serial_port *port = urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	struct tty_struct *tty;
+	int result;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (urb->status) {
+		dbg("%s - nonzero read bulk status received: %d",
+		    __FUNCTION__, urb->status);
+		/* something happened, so free up the memory for this urb */
+		if (urb->transfer_buffer) {
+			kfree (urb->transfer_buffer);
+			urb->transfer_buffer = NULL;
+		}
+		return;
+	}
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+
+	tty = port->tty;
+	if (tty && urb->actual_length) {
+		tty_insert_flip_string (tty, data, urb->actual_length);
+		tty_flip_buffer_push (tty);
+	}
+
+	result = usb_submit_urb (urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+			__FUNCTION__, result);
+	return;
+}
+
+static void airprime_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_serial_port *port = urb->context;
+	struct airprime_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* free up the transfer buffer, as usb_free_urb() does not do this */
+	kfree (urb->transfer_buffer);
+
+	if (urb->status)
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, urb->status);
+	spin_lock_irqsave(&priv->lock, flags);
+	--priv->outstanding_urbs;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	usb_serial_port_softint(port);
+}
+
+static int airprime_open(struct usb_serial_port *port, struct file *filp)
+{
+	struct airprime_private *priv = usb_get_serial_port_data(port);
+	struct usb_serial *serial = port->serial;
+	struct urb *urb;
+	char *buffer = NULL;
+	int i;
+	int result = 0;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* initialize our private data structure if it isn't already created */
+	if (!priv) {
+		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+		if (!priv) {
+			result = -ENOMEM;
+			goto out;
+		}
+		spin_lock_init(&priv->lock);
+		usb_set_serial_port_data(port, priv);
+	}
+
+	for (i = 0; i < NUM_READ_URBS; ++i) {
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (!buffer) {
+			dev_err(&port->dev, "%s - out of memory.\n",
+				__FUNCTION__);
+			result = -ENOMEM;
+			goto errout;
+		}
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			dev_err(&port->dev, "%s - no more urbs?\n",
+				__FUNCTION__);
+			result = -ENOMEM;
+			goto errout;
+		}
+		usb_fill_bulk_urb(urb, serial->dev,
+				  usb_rcvbulkpipe(serial->dev,
+						  port->bulk_out_endpointAddress),
+				  buffer, buffer_size,
+				  airprime_read_bulk_callback, port);
+		result = usb_submit_urb(urb, GFP_KERNEL);
+		if (result) {
+			dev_err(&port->dev,
+				"%s - failed submitting read urb %d for port %d, error %d\n",
+				__FUNCTION__, i, port->number, result);
+			goto errout;
+		}
+		/* remember this urb so we can kill it when the port is closed */
+		priv->read_urbp[i] = urb;
+	}
+	goto out;
+
+ errout:
+	/* some error happened, cancel any submitted urbs and clean up anything that
+	   got allocated successfully */
+
+	for ( ; i >= 0; --i) {
+		urb = priv->read_urbp[i];
+		if (urb) {
+			/* This urb was submitted successfully. So we have to
+			   cancel it.
+			   Unlinking the urb will invoke read_bulk_callback()
+			   with an error status, so its transfer buffer will
+			   be freed there */
+			if (usb_unlink_urb (urb) != -EINPROGRESS) {
+				/* comments in drivers/usb/core/urb.c say this
+				   can only happen if the urb was never submitted,
+				   or has completed already.
+				   Either way we may have to free the transfer
+				   buffer here. */
+				if (urb->transfer_buffer) {
+					kfree (urb->transfer_buffer);
+					urb->transfer_buffer = NULL;
+				}
+			}
+			usb_free_urb (urb);
+		}
+	}
+
+ out:
+	return result;
+}
+
+static void airprime_close(struct usb_serial_port *port, struct file * filp)
+{
+	struct airprime_private *priv = usb_get_serial_port_data(port);
+	int i;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* killing the urb will invoke read_bulk_callback() with an error status,
+	   so the transfer buffer will be freed there */
+	for (i = 0; i < NUM_READ_URBS; ++i) {
+		usb_kill_urb (priv->read_urbp[i]);
+		usb_free_urb (priv->read_urbp[i]);
+	}
+
+	/* free up private structure */
+	kfree (priv);
+	usb_set_serial_port_data(port, NULL);
+}
+
+static int airprime_write(struct usb_serial_port *port,
+			  const unsigned char *buf, int count)
+{
+	struct airprime_private *priv = usb_get_serial_port_data(port);
+	struct usb_serial *serial = port->serial;
+	struct urb *urb;
+	unsigned char *buffer;
+	unsigned long flags;
+	int status;
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->outstanding_urbs > NUM_WRITE_URBS) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		dbg("%s - write limit hit\n", __FUNCTION__);
+		return 0;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+	buffer = kmalloc(count, GFP_ATOMIC);
+	if (!buffer) {
+		dev_err(&port->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		dev_err(&port->dev, "no more free urbs\n");
+		kfree (buffer);
+		return -ENOMEM;
+	}
+	memcpy (buffer, buf, count);
+
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+	usb_fill_bulk_urb(urb, serial->dev,
+			  usb_sndbulkpipe(serial->dev,
+					  port->bulk_out_endpointAddress),
+			  buffer, count,
+			  airprime_write_bulk_callback, port);
+
+	/* send it down the pipe */
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status) {
+		dev_err(&port->dev,
+			"%s - usb_submit_urb(write bulk) failed with status = %d\n",
+			__FUNCTION__, status);
+		count = status;
+		kfree (buffer);
+	} else {
+		spin_lock_irqsave(&priv->lock, flags);
+		++priv->outstanding_urbs;
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+	/* we are done with this urb, so let the host driver
+	 * really free it when it is finished with it */
+	usb_free_urb (urb);
+	return count;
+}
+
 static struct usb_driver airprime_driver = {
 	.name =		"airprime",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
+	.no_dynamic_id =	1,
 };
 
 static struct usb_serial_driver airprime_device = {
@@ -42,13 +280,17 @@
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
 	.num_bulk_out =		NUM_DONT_CARE,
-	.num_ports =		1,
+	.open =			airprime_open,
+	.close =		airprime_close,
+	.write =		airprime_write,
 };
 
 static int __init airprime_init(void)
 {
 	int retval;
 
+	airprime_device.num_ports =
+		(endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS;
 	retval = usb_serial_register(&airprime_device);
 	if (retval)
 		return retval;
@@ -60,6 +302,8 @@
 
 static void __exit airprime_exit(void)
 {
+	dbg("%s", __FUNCTION__);
+
 	usb_deregister(&airprime_driver);
 	usb_serial_deregister(&airprime_device);
 }
@@ -67,3 +311,10 @@
 module_init(airprime_init);
 module_exit(airprime_exit);
 MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled");
+module_param(buffer_size, int, 0);
+MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)");
+module_param(endpoints, int, 0);
+MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 970d9ef..ca52f12 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2006
+ *   Simon Schulz (ark3116_driver <at> auctionant.de)
+ *
  * ark3116
  * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
  *   productid=0x0232) (used in a datacable called KQ-U8A)
@@ -8,8 +11,6 @@
  *
  *  - based on logs created by usbsnoopy
  *
- *  Author   : Simon Schulz [ark3116_driver<AT>auctionant.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
@@ -22,6 +23,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/serial.h>
+#include <asm/uaccess.h>
 
 
 static int debug;
@@ -43,10 +46,10 @@
 {
 	int result;
 	result = usb_control_msg(serial->dev,
-				 usb_sndctrlpipe(serial->dev,0),
+				 usb_sndctrlpipe(serial->dev, 0),
 				 request, requesttype, value, index,
-				 NULL,0x00, 1000);
-	dbg("%03d > ok",seq);
+				 NULL, 0x00, 1000);
+	dbg("%03d > ok", seq);
 }
 
 static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
@@ -56,27 +59,25 @@
 {
 	int result;
 	result = usb_control_msg(serial->dev,
-			      usb_rcvctrlpipe(serial->dev,0),
-			      request, requesttype, value, index,
-			      buf, 0x0000001, 1000);
+				 usb_rcvctrlpipe(serial->dev, 0),
+				 request, requesttype, value, index,
+				 buf, 0x0000001, 1000);
 	if (result)
-		dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]);
+		dbg("%03d < %d bytes [0x%02X]", seq, result, buf[0]);
 	else
 		dbg("%03d < 0 bytes", seq);
 }
 
-
 static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
 				     __u8 request, __u8 requesttype,
 				     __u16 value, __u16 index, char *buf)
 {
 	usb_control_msg(serial->dev,
-			usb_rcvctrlpipe(serial->dev,0),
+			usb_rcvctrlpipe(serial->dev, 0),
 			request, requesttype, value, index,
 			buf, 0x0000001, 1000);
 }
 
-
 static int ark3116_attach(struct usb_serial *serial)
 {
 	char *buf;
@@ -84,10 +85,10 @@
 	int i;
 
 	for (i = 0; i < serial->num_ports; ++i) {
-		priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL);
+		priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL);
 		if (!priv)
 			goto cleanup;
-		memset (priv, 0x00, sizeof (struct ark3116_private));
+		memset(priv, 0x00, sizeof (struct ark3116_private));
 		spin_lock_init(&priv->lock);
 
 		usb_set_serial_port_data(serial->port[i], priv);
@@ -95,63 +96,62 @@
 
 	buf = kmalloc(1, GFP_KERNEL);
 	if (!buf) {
-		dbg("error kmalloc -> out of mem ?");
+		dbg("error kmalloc -> out of mem?");
 		goto cleanup;
 	}
 
 	/* 3 */
-	ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002);
-	ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001);
-	ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008);
-	ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B);
+	ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002);
+	ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001);
+	ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008);
+	ARK3116_SND(serial, 6, 0xFE, 0x40, 0x0000, 0x000B);
 
 	/* <-- seq7 */
-	ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf);
-	ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003);
-	ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000);
-	ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001);
-	ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003);
+	ARK3116_RCV(serial,  7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+	ARK3116_SND(serial,  8, 0xFE, 0x40, 0x0080, 0x0003);
+	ARK3116_SND(serial,  9, 0xFE, 0x40, 0x001A, 0x0000);
+	ARK3116_SND(serial, 10, 0xFE, 0x40, 0x0000, 0x0001);
+	ARK3116_SND(serial, 11, 0xFE, 0x40, 0x0000, 0x0003);
 
 	/* <-- seq12 */
-	ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
-	ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004);
+	ARK3116_RCV(serial, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
+	ARK3116_SND(serial, 13, 0xFE, 0x40, 0x0000, 0x0004);
 
 	/* 14 */
-	ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
-	ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004);
+	ARK3116_RCV(serial, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
+	ARK3116_SND(serial, 15, 0xFE, 0x40, 0x0000, 0x0004);
 
 	/* 16 */
-	ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+	ARK3116_RCV(serial, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
 	/* --> seq17 */
-	ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004);
+	ARK3116_SND(serial, 17, 0xFE, 0x40, 0x0001, 0x0004);
 
 	/* <-- seq18 */
-	ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+	ARK3116_RCV(serial, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf);
 
 	/* --> seq19 */
-	ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004);
-
+	ARK3116_SND(serial, 19, 0xFE, 0x40, 0x0003, 0x0004);
 
 	/* <-- seq20 */
-	/* seems like serial port status info (RTS, CTS,...) */
-	/* returns modem control line status ?! */
-	ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+	/* seems like serial port status info (RTS, CTS, ...) */
+	/* returns modem control line status?! */
+	ARK3116_RCV(serial, 20, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
 
-	/* set 9600 baud & do some init ?! */
-	ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
-	ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000);
-	ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001);
-	ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
-	ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
-	ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
-	ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
-	ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003);
+	/* set 9600 baud & do some init?! */
+	ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003);
+	ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000);
+	ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001);
+	ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003);
+	ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+	ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003);
+	ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+	ARK3116_SND(serial, 154, 0xFE, 0x40, 0x0003, 0x0003);
 
 	kfree(buf);
-	return(0);
+	return 0;
 
 cleanup:
-	for (--i; i>=0; --i)
+	for (--i; i >= 0; --i)
 		usb_set_serial_port_data(serial->port[i], NULL);
 	return -ENOMEM;
 }
@@ -180,7 +180,8 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	if (!priv->termios_initialized) {
 		*(port->tty->termios) = tty_std_termios;
-		port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+		port->tty->termios->c_cflag = B9600 | CS8
+					      | CREAD | HUPCL | CLOCAL;
 		priv->termios_initialized = 1;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -204,8 +205,8 @@
 	}
 
 	/* set data bit count (8/7/6/5) */
-	if (cflag & CSIZE){
-		switch (cflag & CSIZE){
+	if (cflag & CSIZE) {
+		switch (cflag & CSIZE) {
 		case CS5:
 			config |= 0x00;
 			dbg("setting CS5");
@@ -219,7 +220,8 @@
 			dbg("setting CS7");
 			break;
 		default:
-			err ("CSIZE was set but not CS5-CS8, using CS8!");
+			err("CSIZE was set but not CS5-CS8, using CS8!");
+			/* fall through */
 		case CS8:
 			config |= 0x03;
 			dbg("setting CS8");
@@ -227,8 +229,8 @@
 		}
 	}
 
-	/* set parity (NONE,EVEN,ODD) */
-	if (cflag & PARENB){
+	/* set parity (NONE/EVEN/ODD) */
+	if (cflag & PARENB) {
 		if (cflag & PARODD) {
 			config |= 0x08;
 			dbg("setting parity to ODD");
@@ -240,20 +242,19 @@
 		dbg("setting parity to NONE");
 	}
 
-	/* SET STOPBIT (1/2) */
+	/* set stop bit (1/2) */
 	if (cflag & CSTOPB) {
 		config |= 0x04;
-		dbg ("setting 2 stop bits");
+		dbg("setting 2 stop bits");
 	} else {
-		dbg ("setting 1 stop bit");
+		dbg("setting 1 stop bit");
 	}
 
-
-	/* set baudrate: */
+	/* set baudrate */
 	baud = 0;
-	switch (cflag & CBAUD){
+	switch (cflag & CBAUD) {
 		case B0:
-			err("can't set 0baud, using 9600 instead");
+			err("can't set 0 baud, using 9600 instead");
 			break;
 		case B75:	baud = 75;	break;
 		case B150:	baud = 150;	break;
@@ -285,38 +286,40 @@
 	 */
 	if (baud == 460800)
 		/* strange, for 460800 the formula is wrong
-		 * (dont use round(), then 9600baud is wrong) */
+		 * if using round() then 9600baud is wrong) */
 		ark3116_baud = 7;
 	else
 		ark3116_baud = 3000000 / baud;
 
 	/* ? */
-	ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf);
+	ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf);
+
 	/* offset = buf[0]; */
 	/* offset = 0x03; */
-	/* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */
-
+	/* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */
 
 	/* set baudrate */
-	dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud);
-	ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
-	ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF)   ,0x0000);
-	ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001);
-	ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
+	dbg("setting baudrate to %d (->reg=%d)", baud, ark3116_baud);
+	ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003);
+	ARK3116_SND(serial, 148, 0xFE, 0x40,
+			    (ark3116_baud & 0x00FF), 0x0000);
+	ARK3116_SND(serial, 149, 0xFE, 0x40,
+			    (ark3116_baud & 0xFF00) >> 8, 0x0001);
+	ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003);
 
 	/* ? */
-	ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
-	ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
+	ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+	ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003);
 
 	/* set data bit count, stop bit count & parity: */
 	dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config);
-	ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
-	ARK3116_SND(serial,154,0xFE,0x40,config,0x0003);
+	ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+	ARK3116_SND(serial, 154, 0xFE, 0x40, config, 0x0003);
 
 	if (cflag & CRTSCTS)
-		dbg("CRTSCTS not supported by chipset ?!");
+		dbg("CRTSCTS not supported by chipset?!");
 
-	/* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */
+	/* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */
 
 	kfree(buf);
 	return;
@@ -329,11 +332,11 @@
 	char *buf;
 	int result = 0;
 
-	dbg("%s -  port %d", __FUNCTION__, port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	buf = kmalloc(1, GFP_KERNEL);
 	if (!buf) {
-		dbg("error kmalloc -> out of mem ?");
+		dbg("error kmalloc -> out of mem?");
 		return -ENOMEM;
 	}
 
@@ -342,44 +345,68 @@
 		return result;
 
 	/* open */
-	ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf);
+	ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf);
 
-	ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003);
-	ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000);
-	ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001);
-	ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003);
+	ARK3116_SND(serial, 112, 0xFE, 0x40, 0x0082, 0x0003);
+	ARK3116_SND(serial, 113, 0xFE, 0x40, 0x001A, 0x0000);
+	ARK3116_SND(serial, 114, 0xFE, 0x40, 0x0000, 0x0001);
+	ARK3116_SND(serial, 115, 0xFE, 0x40, 0x0002, 0x0003);
 
-	ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf);
-	ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004);
+	ARK3116_RCV(serial, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+	ARK3116_SND(serial, 117, 0xFE, 0x40, 0x0002, 0x0004);
 
-	ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf);
-	ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004);
+	ARK3116_RCV(serial, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf);
+	ARK3116_SND(serial, 119, 0xFE, 0x40, 0x0000, 0x0004);
 
-	ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+	ARK3116_RCV(serial, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
 
-	ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004);
+	ARK3116_SND(serial, 121, 0xFE, 0x40, 0x0001, 0x0004);
 
-	ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+	ARK3116_RCV(serial, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf);
 
-	ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004);
+	ARK3116_SND(serial, 123, 0xFE, 0x40, 0x0003, 0x0004);
 
-	/* returns different values (control lines ?!) */
-	ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+	/* returns different values (control lines?!) */
+	ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
 
-	/* initialise termios: */
+	/* initialise termios */
 	if (port->tty)
 		ark3116_set_termios(port, &tmp_termios);
 
 	kfree(buf);
 
 	return result;
-
 }
 
 static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
-	dbg("ioctl not supported yet...");
+	struct serial_struct serstruct;
+	void __user *user_arg = (void __user *)arg;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		/* XXX: Some of these values are probably wrong. */
+		memset(&serstruct, 0, sizeof (serstruct));
+		serstruct.type = PORT_16654;
+		serstruct.line = port->serial->minor;
+		serstruct.port = port->number;
+		serstruct.custom_divisor = 0;
+		serstruct.baud_base = 460800;
+
+		if (copy_to_user(user_arg, &serstruct, sizeof (serstruct)))
+			return -EFAULT;
+
+		return 0;
+	case TIOCSSERIAL:
+		if (copy_from_user(&serstruct, user_arg, sizeof (serstruct)))
+			return -EFAULT;
+		return 0;
+	default:
+		dbg("%s cmd 0x%04x not supported", __FUNCTION__, cmd);
+		break;
+	}
+
 	return -ENOIOCTLCMD;
 }
 
@@ -389,7 +416,7 @@
 	char *buf;
 	char temp;
 
-	/* seems like serial port status info (RTS, CTS,...) is stored
+	/* seems like serial port status info (RTS, CTS, ...) is stored
 	 * in reg(?) 0x0006
 	 * pcb connection point 11 = GND -> sets bit4 of response
 	 * pcb connection point  7 = GND -> sets bit6 of response
@@ -401,16 +428,16 @@
 		return -ENOMEM;
 	}
 
-	/* read register: */
-	ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf);
+	/* read register */
+	ARK3116_RCV_QUIET(serial, 0xFE, 0xC0, 0x0000, 0x0006, buf);
 	temp = buf[0];
 	kfree(buf);
 
-	/* i do not really know if bit4=CTS and bit6=DSR... was just a
-	 * quick guess !!
+	/* i do not really know if bit4=CTS and bit6=DSR... just a
+	 * quick guess!
 	 */
-	return  (temp & (1<<4) ? TIOCM_CTS : 0) |
-	        (temp & (1<<6) ? TIOCM_DSR : 0);
+	return (temp & (1<<4) ? TIOCM_CTS : 0)
+	       | (temp & (1<<6) ? TIOCM_DSR : 0);
 }
 
 static struct usb_driver ark3116_driver = {
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 6286aba..d954ec3 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -214,14 +214,14 @@
 		return (0);
 	}
 
-	spin_lock(&port->lock);
+	spin_lock_bh(&port->lock);
 	if (port->write_urb_busy) {
-		spin_unlock(&port->lock);
+		spin_unlock_bh(&port->lock);
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
 	}
 	port->write_urb_busy = 1;
-	spin_unlock(&port->lock);
+	spin_unlock_bh(&port->lock);
 
 	spin_lock_irqsave(&priv->lock, flags);
 
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index ee70fdd..e1173c1 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -129,6 +129,9 @@
 	int cmd_ctrl;			   /* always set this to 1 before issuing a command */
 	struct cypress_buf *buf;	   /* write buffer */
 	int write_urb_in_use;		   /* write urb in use indicator */
+	int write_urb_interval;            /* interval to use for write urb */
+	int read_urb_interval;             /* interval to use for read urb */
+	int comm_is_ok;                    /* true if communication is (still) ok */
 	int termios_initialized;
 	__u8 line_control;	   	   /* holds dtr / rts value */
 	__u8 current_status;	   	   /* received from last read - info on dsr,cts,cd,ri,etc */
@@ -168,6 +171,7 @@
 static int  cypress_chars_in_buffer	(struct usb_serial_port *port);
 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);
 /* baud helper functions */
@@ -288,6 +292,9 @@
 	
 	priv = usb_get_serial_port_data(port);
 
+	if (!priv->comm_is_ok)
+		return -ENODEV;
+
 	switch(cypress_request_type) {
 		case CYPRESS_SET_CONFIG:
 
@@ -365,13 +372,12 @@
 				if (tries++ >= 3)
 					break;
 
-				if (retval == EPIPE)
-					usb_clear_halt(port->serial->dev, 0x00);
-			} while (retval != 8 && retval != ENODEV);
+			} while (retval != 8 && retval != -ENODEV);
 
-			if (retval != 8)
+			if (retval != 8) {
 				err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
-			else {
+				cypress_set_dead(port);
+			} else {
 				spin_lock_irqsave(&priv->lock, flags);
 				priv->baud_rate = new_baudrate;
 				priv->cbr_mask = baud_mask;
@@ -392,12 +398,11 @@
 				if (tries++ >= 3)
 					break;
 
-				if (retval == EPIPE)
-					usb_clear_halt(port->serial->dev, 0x00);
-			} while (retval != 5 && retval != ENODEV);
+			} while (retval != 5 && retval != -ENODEV);
 
 			if (retval != 5) {
 				err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
+				cypress_set_dead(port);
 				return retval;
 			} else {
 				spin_lock_irqsave(&priv->lock, flags);
@@ -419,6 +424,24 @@
 } /* cypress_serial_control */
 
 
+static void cypress_set_dead(struct usb_serial_port *port)
+{
+	struct cypress_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->comm_is_ok) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+	priv->comm_is_ok = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	err("cypress_m8 suspending failing port %d - interval might be too short",
+	    port->number);
+}
+
+
 /* given a baud mask, it will return integer baud on success */
 static int mask_to_rate (unsigned mask)
 {
@@ -472,13 +495,15 @@
 static int generic_startup (struct usb_serial *serial)
 {
 	struct cypress_private *priv;
+	struct usb_serial_port *port = serial->port[0];
 
-	dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+	priv->comm_is_ok = !0;
 	spin_lock_init(&priv->lock);
 	priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE);
 	if (priv->buf == NULL) {
@@ -489,13 +514,24 @@
 	
 	usb_reset_configuration (serial->dev);
 	
-	interval = 1;
 	priv->cmd_ctrl = 0;
 	priv->line_control = 0;
 	priv->termios_initialized = 0;
 	priv->rx_flags = 0;
 	priv->cbr_mask = B300;
-	usb_set_serial_port_data(serial->port[0], priv);
+	if (interval > 0) {
+		priv->write_urb_interval = interval;
+		priv->read_urb_interval = interval;
+		dbg("%s - port %d read & write intervals forced to %d",
+		    __FUNCTION__,port->number,interval);
+	} else {
+		priv->write_urb_interval = port->interrupt_out_urb->interval;
+		priv->read_urb_interval = port->interrupt_in_urb->interval;
+		dbg("%s - port %d intervals: read=%d write=%d",
+		    __FUNCTION__,port->number,
+		    priv->read_urb_interval,priv->write_urb_interval);
+	}
+	usb_set_serial_port_data(port, priv);
 	
 	return 0;
 }
@@ -585,6 +621,9 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	if (!priv->comm_is_ok)
+		return -EIO;
+
 	/* clear halts before open */
 	usb_clear_halt(serial->dev, 0x81);
 	usb_clear_halt(serial->dev, 0x02);
@@ -624,11 +663,12 @@
 	usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
 		usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
 		port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
-		cypress_read_int_callback, port, interval);
+		cypress_read_int_callback, port, priv->read_urb_interval);
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 
 	if (result){
 		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+		cypress_set_dead(port);
 	}
 
 	return result;
@@ -733,6 +773,9 @@
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	
+	if (!priv->comm_is_ok)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
 	
@@ -806,14 +849,16 @@
 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
 			      port->interrupt_out_urb->transfer_buffer);
 
-	port->interrupt_out_urb->transfer_buffer_length = actual_size;
-	port->interrupt_out_urb->dev = port->serial->dev;
-	port->interrupt_out_urb->interval = interval;
+	usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
+		usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
+		port->interrupt_out_buffer, port->interrupt_out_size,
+		cypress_write_int_callback, port, priv->write_urb_interval);
 	result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
 			result);
 		priv->write_urb_in_use = 0;
+		cypress_set_dead(port);
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -1214,13 +1259,18 @@
 	priv->rx_flags = 0;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
+	if (!priv->comm_is_ok)
+		return;
+
 	if (actually_throttled) {
 		port->interrupt_in_urb->dev = port->serial->dev;
 
 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-		if (result)
+		if (result) {
 			dev_err(&port->dev, "%s - failed submitting read urb, "
 					"error %d\n", __FUNCTION__, result);
+			cypress_set_dead(port);
+		}
 	}
 }
 
@@ -1240,9 +1290,22 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (urb->status) {
-		dbg("%s - nonzero read status received: %d", __FUNCTION__,
-				urb->status);
+	switch (urb->status) {
+	case 0: /* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* precursor to disconnect so just go away */
+		return;
+	case -EPIPE:
+		usb_clear_halt(port->serial->dev,0x81);
+		break;
+	default:
+		/* something ugly is going on... */
+		dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
+			__FUNCTION__,urb->status);
+		cypress_set_dead(port);
 		return;
 	}
 
@@ -1343,18 +1406,20 @@
 
 	/* Continue trying to always read... unless the port has closed. */
 
-	if (port->open_count > 0) {
+	if (port->open_count > 0 && priv->comm_is_ok) {
 		usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
 				usb_rcvintpipe(port->serial->dev,
 					port->interrupt_in_endpointAddress),
 				port->interrupt_in_urb->transfer_buffer,
 				port->interrupt_in_urb->transfer_buffer_length,
-				cypress_read_int_callback, port, interval);
+				cypress_read_int_callback, port, priv->read_urb_interval);
 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-		if (result)
+		if (result) {
 			dev_err(&urb->dev->dev, "%s - failed resubmitting "
 					"read urb, error %d\n", __FUNCTION__,
 					result);
+			cypress_set_dead(port);
+		}
 	}
 
 	return;
@@ -1380,20 +1445,26 @@
 			dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
 			priv->write_urb_in_use = 0;
 			return;
-		case -EPIPE: /* no break needed */
+		case -EPIPE: /* no break needed; clear halt and resubmit */
+			if (!priv->comm_is_ok)
+				break;
 			usb_clear_halt(port->serial->dev, 0x02);
-		default:
 			/* error in the urb, so we have to resubmit it */
-			dbg("%s - Overflow in write", __FUNCTION__);
 			dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
 			port->interrupt_out_urb->transfer_buffer_length = 1;
 			port->interrupt_out_urb->dev = port->serial->dev;
 			result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
-			if (result)
-				dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
-					__FUNCTION__, result);
-			else
+			if (!result)
 				return;
+			dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
+				__FUNCTION__, result);
+			cypress_set_dead(port);
+			break;
+		default:
+			dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
+				__FUNCTION__,urb->status);
+			cypress_set_dead(port);
+			break;
 	}
 	
 	priv->write_urb_in_use = 0;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c6115aa..e774a27 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -344,6 +344,7 @@
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) },
@@ -507,6 +508,9 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
 	{ USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -1101,25 +1105,29 @@
 static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
 static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
 
-static void create_sysfs_attrs(struct usb_serial *serial)
-{	
+static int create_sysfs_attrs(struct usb_serial *serial)
+{
 	struct ftdi_private *priv;
 	struct usb_device *udev;
+	int retval = 0;
 
 	dbg("%s",__FUNCTION__);
-	
+
 	priv = usb_get_serial_port_data(serial->port[0]);
 	udev = serial->dev;
-	
+
 	/* XXX I've no idea if the original SIO supports the event_char
 	 * sysfs parameter, so I'm playing it safe.  */
 	if (priv->chip_type != SIO) {
 		dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
-		device_create_file(&udev->dev, &dev_attr_event_char);
-		if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
-			device_create_file(&udev->dev, &dev_attr_latency_timer);
+		retval = device_create_file(&udev->dev, &dev_attr_event_char);
+		if ((!retval) &&
+		    (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
+			retval = device_create_file(&udev->dev,
+						    &dev_attr_latency_timer);
 		}
 	}
+	return retval;
 }
 
 static void remove_sysfs_attrs(struct usb_serial *serial)
@@ -1162,7 +1170,8 @@
 	struct usb_serial_port *port = serial->port[0];
 	struct ftdi_private *priv;
 	struct ftdi_sio_quirk *quirk;
-	
+	int retval;
+
 	dbg("%s",__FUNCTION__);
 
 	priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
@@ -1203,15 +1212,18 @@
 	usb_set_serial_port_data(serial->port[0], priv);
 
 	ftdi_determine_type (serial->port[0]);
-	create_sysfs_attrs(serial);
+	retval = create_sysfs_attrs(serial);
+	if (retval)
+		dev_err(&serial->dev->dev, "Error creating sysfs files, "
+			"continuing\n");
 
 	/* Check for device requiring special set up. */
 	quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
 	if (quirk && quirk->setup) {
 		quirk->setup(serial);
 	}
-	
-	return (0);
+
+	return 0;
 } /* ftdi_sio_attach */
 
 
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 7729999..f0edb87 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -111,6 +111,7 @@
 #define SEALEVEL_2102_PID	0x2102	/* SeaLINK+485 (2102) */
 #define SEALEVEL_2103_PID	0x2103	/* SeaLINK+232I (2103) */
 #define SEALEVEL_2104_PID	0x2104	/* SeaLINK+485I (2104) */
+#define SEALEVEL_2106_PID	0x9020	/* SeaLINK+422 (2106) */
 #define SEALEVEL_2201_1_PID	0x2211	/* SeaPORT+2/232 (2201) Port 1 */
 #define SEALEVEL_2201_2_PID	0x2221	/* SeaPORT+2/232 (2201) Port 2 */
 #define SEALEVEL_2202_1_PID	0x2212	/* SeaPORT+2/485 (2202) Port 1 */
@@ -472,6 +473,15 @@
  */
 #define FTDI_GAMMA_SCOUT_PID		0xD678	/* Gamma Scout online */
 
+/*
+ * Tactrix OpenPort (ECU) devices.
+ * OpenPort 1.3M submitted by Donour Sizemore.
+ * OpenPort 1.3S and 1.3U submitted by Ian Abbott.
+ */
+#define FTDI_TACTRIX_OPENPORT_13M_PID	0xCC48	/* OpenPort 1.3 Mitsubishi */
+#define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
+#define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 7278526..4b1196a 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1,7 +1,7 @@
 /*
  * Garmin GPS driver
  *
- * Copyright (C) 2004 Hermann Kneissel herkne@users.sourceforge.net
+ * Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net
  *
  * The latest version of the driver can be found at
  * http://sourceforge.net/projects/garmin-gps/
@@ -37,6 +37,8 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
+#include <linux/version.h>
+
 /* the mode to be set when the port ist opened */
 static int initial_mode = 1;
 
@@ -50,7 +52,7 @@
  */
 
 #define VERSION_MAJOR	0
-#define VERSION_MINOR	23
+#define VERSION_MINOR	28
 
 #define _STR(s) #s
 #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
@@ -164,7 +166,8 @@
 #define FLAGS_SESSION_REPLY1_SEEN 0x0080
 #define FLAGS_SESSION_REPLY2_SEEN 0x0040
 #define FLAGS_BULK_IN_ACTIVE      0x0020
-#define FLAGS_THROTTLED           0x0010
+#define FLAGS_BULK_IN_RESTART     0x0010
+#define FLAGS_THROTTLED           0x0008
 #define CLEAR_HALT_REQUIRED       0x0001
 
 #define FLAGS_QUEUING             0x0100
@@ -224,7 +227,7 @@
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
-	.no_dynamic_id = 	1,
+	.no_dynamic_id = 1,
 };
 
 
@@ -270,7 +273,7 @@
 
 
 static void send_to_tty(struct usb_serial_port *port,
-                        char *data, unsigned int actual_length)
+			char *data, unsigned int actual_length)
 {
 	struct tty_struct *tty = port->tty;
 
@@ -294,15 +297,15 @@
  * queue a received (usb-)packet for later processing
  */
 static int pkt_add(struct garmin_data * garmin_data_p,
-                   unsigned char *data, unsigned int data_length)
+		   unsigned char *data, unsigned int data_length)
 {
+	int state = 0;
 	int result = 0;
 	unsigned long flags;
 	struct garmin_packet *pkt;
 
 	/* process only packets containg data ... */
 	if (data_length) {
-		garmin_data_p->flags |= FLAGS_QUEUING;
 		pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
 		              GFP_ATOMIC);
 		if (pkt == NULL) {
@@ -313,14 +316,16 @@
 		memcpy(pkt->data, data, data_length);
 
 		spin_lock_irqsave(&garmin_data_p->lock, flags);
+		garmin_data_p->flags |= FLAGS_QUEUING;
 		result = list_empty(&garmin_data_p->pktlist);
 		pkt->seq = garmin_data_p->seq_counter++;
 		list_add_tail(&pkt->list, &garmin_data_p->pktlist);
+		state = garmin_data_p->state;
 		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 		/* in serial mode, if someone is waiting for data from
 		   the device, iconvert and send the next packet to tty. */
-		if (result && (garmin_data_p->state == STATE_GSP_WAIT_DATA)) {
+		if (result && (state == STATE_GSP_WAIT_DATA)) {
 			gsp_next_packet(garmin_data_p);
 		}
 	}
@@ -370,9 +375,9 @@
 static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
 {
 	__u8 pkt[10];
-        __u8 cksum = 0;
-        __u8 *ptr = pkt;
-        unsigned  l = 0;
+	__u8 cksum = 0;
+	__u8 *ptr = pkt;
+	unsigned  l = 0;
 
 	dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
 
@@ -416,7 +421,7 @@
 static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
 {
 	const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
-        __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
+	__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
 
 	int cksum = 0;
 	int n = 0;
@@ -447,11 +452,11 @@
 		n++;
 	}
 
-       if ((0xff & (cksum + *recpkt)) != 0) {
-                dbg("%s - invalid checksum, expected %02x, got %02x",
-                        __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
-                return -EINVPKT;
-        }
+	if ((0xff & (cksum + *recpkt)) != 0) {
+		dbg("%s - invalid checksum, expected %02x, got %02x",
+			__FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
+		return -EINVPKT;
+	}
 
 	usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
 	usbdata[1] = __cpu_to_le32(pktid);
@@ -491,20 +496,28 @@
  */
 
 static int gsp_receive(struct garmin_data * garmin_data_p,
-                       const unsigned char *buf, int count)
+		       const unsigned char *buf, int count)
 {
+	unsigned long flags;
 	int offs = 0;
 	int ack_or_nak_seen = 0;
 	int i = 0;
-	__u8 *dest = garmin_data_p->inbuffer;
-	int size = garmin_data_p->insize;
+	__u8 *dest;
+	int size;
 	// dleSeen: set if last byte read was a DLE
-	int dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
+	int dleSeen;
 	// skip: if set, skip incoming data until possible start of
 	//       new packet
-	int skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
+	int skip;
 	__u8 data;
 
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
+	dest = garmin_data_p->inbuffer;
+	size = garmin_data_p->insize;
+	dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
+	skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
 	dbg("%s - dle=%d skip=%d size=%d count=%d",
 		__FUNCTION__, dleSeen, skip, size, count);
 
@@ -572,6 +585,8 @@
 		}
 	}
 
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
+
 	garmin_data_p->insize = size;
 
 	// copy flags back to structure
@@ -587,6 +602,11 @@
 
 	if (ack_or_nak_seen) {
 		garmin_data_p->state = STATE_GSP_WAIT_DATA;
+	}
+
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+	if (ack_or_nak_seen) {
 		gsp_next_packet(garmin_data_p);
 	}
 
@@ -676,7 +696,7 @@
 	src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
 	if (k > (GARMIN_PKTHDR_LENGTH-2)) {
 		/* can't add stuffing DLEs in place, move data to end 
-                   of buffer ... */
+		   of buffer ... */
 		dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
 		memcpy(dst, src, datalen);
 		src = dst;
@@ -755,8 +775,9 @@
  * or even incomplete packets
  */
 static int nat_receive(struct garmin_data * garmin_data_p,
-                       const unsigned char *buf, int count)
+		       const unsigned char *buf, int count)
 {
+	unsigned long flags;
 	__u8 * dest;
 	int offs = 0;
 	int result = count;
@@ -803,7 +824,9 @@
 				/* if this was an abort-transfer command,
 				   flush all queued data. */
 				if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
+					spin_lock_irqsave(&garmin_data_p->lock, flags);
 					garmin_data_p->flags |= FLAGS_DROP_DATA;
+					spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 					pkt_clear(garmin_data_p);
 				}
 			}
@@ -839,12 +862,15 @@
 
 static int process_resetdev_request(struct usb_serial_port *port)
 {
+	unsigned long flags;
 	int status;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
 	garmin_data_p->state = STATE_RESET;
 	garmin_data_p->serial_num = 0;
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	usb_kill_urb (port->interrupt_in_urb);
 	dbg("%s - usb_reset_device", __FUNCTION__ );
@@ -862,6 +888,7 @@
  */
 static int garmin_clear(struct garmin_data * garmin_data_p)
 {
+	unsigned long flags;
 	int status = 0;
 
 	struct usb_serial_port *port = garmin_data_p->port;
@@ -875,8 +902,10 @@
 	/* flush all queued data */
 	pkt_clear(garmin_data_p);
 
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->insize = 0;
 	garmin_data_p->outsize = 0;
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	return status;
 }
@@ -888,6 +917,7 @@
 
 static int garmin_init_session(struct usb_serial_port *port)
 {
+	unsigned long flags;
 	struct usb_serial *serial = port->serial;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	int status = 0;
@@ -913,7 +943,9 @@
 
 		if (status >= 0) {
 
+			spin_lock_irqsave(&garmin_data_p->lock, flags);
 			garmin_data_p->ignorePkts++;
+			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 			/* not needed, but the win32 driver does it too ... */
 			status = garmin_write_bulk(port,
@@ -921,7 +953,9 @@
 			                           sizeof(GARMIN_START_SESSION_REQ2));
 			if (status >= 0) {
 				status = 0;
+				spin_lock_irqsave(&garmin_data_p->lock, flags);
 				garmin_data_p->ignorePkts++;
+				spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 			}
 		}
 	}
@@ -935,6 +969,7 @@
 
 static int garmin_open (struct usb_serial_port *port, struct file *filp)
 {
+	unsigned long flags;
 	int status = 0;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
@@ -948,9 +983,11 @@
 	if (port->tty)
 		port->tty->low_latency = 1;
 
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->mode  = initial_mode;
 	garmin_data_p->count = 0;
 	garmin_data_p->flags = 0;
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	/* shutdown any bulk reads that might be going on */
 	usb_kill_urb (port->write_urb);
@@ -996,6 +1033,7 @@
 
 static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
+	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
@@ -1007,7 +1045,9 @@
 	if (urb->status) {
 		dbg("%s - nonzero write bulk status received: %d",
 			__FUNCTION__, urb->status);
+		spin_lock_irqsave(&garmin_data_p->lock, flags);
 		garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
+		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 	}
 
 	usb_serial_port_softint(port);
@@ -1015,8 +1055,9 @@
 
 
 static int garmin_write_bulk (struct usb_serial_port *port,
-                              const unsigned char *buf, int count)
+			      const unsigned char *buf, int count)
 {
+	unsigned long flags;
 	struct usb_serial *serial = port->serial;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	struct urb *urb;
@@ -1026,7 +1067,9 @@
 	dbg("%s - port %d, state %d", __FUNCTION__, port->number,
 		garmin_data_p->state);
 
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->flags &= ~FLAGS_DROP_DATA;
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	buffer = kmalloc (count, GFP_ATOMIC);
 	if (!buffer) {
@@ -1053,7 +1096,9 @@
 	urb->transfer_flags |= URB_ZERO_PACKET;
 
 	if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
+		spin_lock_irqsave(&garmin_data_p->lock, flags);
 		garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 		if (garmin_data_p->mode == MODE_GARMIN_SERIAL)  {
 			pkt_clear(garmin_data_p);
 			garmin_data_p->state = STATE_GSP_WAIT_DATA;
@@ -1087,8 +1132,9 @@
 
 
 static int garmin_write (struct usb_serial_port *port,
-                         const unsigned char *buf, int count)
+			 const unsigned char *buf, int count)
 {
+	unsigned long flags;
 	int pktid, pktsiz, len;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
@@ -1139,7 +1185,9 @@
 				break;
 
 			case PRIV_PKTID_RESET_REQ:
+				spin_lock_irqsave(&garmin_data_p->lock, flags);
 				garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+				spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 				break;
 
 			case PRIV_PKTID_SET_DEF_MODE:
@@ -1155,6 +1203,8 @@
 		}
 	}
 
+	garmin_data_p->ignorePkts = 0;
+
 	if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
 		return gsp_receive(garmin_data_p, buf, count);
 	} else {	/* MODE_NATIVE */
@@ -1177,10 +1227,10 @@
 {
 	/*
 	 * Report back the number of bytes currently in our input buffer.
-         * Will this lock up the driver - the buffer contains an incomplete
-         * package which will not be written to the device until it
-         * has been completed ?
-         */
+	 * Will this lock up the driver - the buffer contains an incomplete
+	 * package which will not be written to the device until it
+	 * has been completed ?
+	 */
 	//struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	//return garmin_data_p->insize;
 	return 0;
@@ -1190,6 +1240,8 @@
 static void garmin_read_process(struct garmin_data * garmin_data_p,
 				 unsigned char *data, unsigned data_length)
 {
+	unsigned long flags;
+
 	if (garmin_data_p->flags & FLAGS_DROP_DATA) {
 		/* abort-transfer cmd is actice */
 		dbg("%s - pkt dropped", __FUNCTION__);
@@ -1200,11 +1252,14 @@
 		   if a reset is required or not when closing
 		   the device */
 		if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
-		                sizeof(GARMIN_APP_LAYER_REPLY)))
+		                sizeof(GARMIN_APP_LAYER_REPLY))) {
+			spin_lock_irqsave(&garmin_data_p->lock, flags);
 			garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
+			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+		}
 
 		/* if throttling is active or postprecessing is required
-		   put the received data in th input queue, otherwise
+		   put the received data in the input queue, otherwise
 		   send it directly to the tty port */
 		if (garmin_data_p->flags & FLAGS_QUEUING) {
 			pkt_add(garmin_data_p, data, data_length);
@@ -1221,6 +1276,7 @@
 
 static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
+	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial =  port->serial;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
@@ -1245,19 +1301,30 @@
 
 	garmin_read_process(garmin_data_p, data, urb->actual_length);
 
-	/* Continue trying to read until nothing more is received  */
-	if (urb->actual_length > 0) {
-		usb_fill_bulk_urb (port->read_urb, serial->dev,
-			   usb_rcvbulkpipe (serial->dev,
-					    port->bulk_in_endpointAddress),
-			   port->read_urb->transfer_buffer,
-			   port->read_urb->transfer_buffer_length,
-			   garmin_read_bulk_callback, port);
+	if (urb->actual_length == 0 &&
+			0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
+		spin_lock_irqsave(&garmin_data_p->lock, flags);
+		garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
+		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 		if (status)
 			dev_err(&port->dev,
 				"%s - failed resubmitting read urb, error %d\n",
 			        __FUNCTION__, status);
+	} else if (urb->actual_length > 0) {
+		/* Continue trying to read until nothing more is received  */
+		if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
+			status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+			if (status)
+				dev_err(&port->dev,
+					"%s - failed resubmitting read urb, error %d\n",
+			        	__FUNCTION__, status);
+		}
+	} else {
+		dbg("%s - end of bulk data", __FUNCTION__);
+		spin_lock_irqsave(&garmin_data_p->lock, flags);
+		garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
+		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 	}
 	return;
 }
@@ -1265,6 +1332,7 @@
 
 static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
 {
+	unsigned long flags;
 	int status;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = port->serial;
@@ -1297,25 +1365,41 @@
 
 		dbg("%s - bulk data available.", __FUNCTION__);
 
-		/* bulk data available */
-		usb_fill_bulk_urb (port->read_urb, serial->dev,
-				usb_rcvbulkpipe (serial->dev,
-				port->bulk_in_endpointAddress),
-				port->read_urb->transfer_buffer,
-				port->read_urb->transfer_buffer_length,
-				garmin_read_bulk_callback, port);
-		status = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (status) {
-			dev_err(&port->dev,
-				"%s - failed submitting read urb, error %d\n",
-			__FUNCTION__, status);
+		if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+
+			/* bulk data available */
+			usb_fill_bulk_urb (port->read_urb, serial->dev,
+					usb_rcvbulkpipe (serial->dev,
+					port->bulk_in_endpointAddress),
+					port->read_urb->transfer_buffer,
+					port->read_urb->transfer_buffer_length,
+					garmin_read_bulk_callback, port);
+			status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+			if (status) {
+				dev_err(&port->dev,
+					"%s - failed submitting read urb, error %d\n",
+				__FUNCTION__, status);
+			} else {
+				spin_lock_irqsave(&garmin_data_p->lock, flags);
+				garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
+				/* do not send this packet to the user */
+				garmin_data_p->ignorePkts = 1;
+				spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+			}
+		} else {
+			/* bulk-in transfer still active */
+			spin_lock_irqsave(&garmin_data_p->lock, flags);
+			garmin_data_p->flags |= FLAGS_BULK_IN_RESTART;
+			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 		}
 
 	} else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
 			 && 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
 			                sizeof(GARMIN_START_SESSION_REPLY))) {
 
+		spin_lock_irqsave(&garmin_data_p->lock, flags);
 		garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
+		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 		/* save the serial number */
 		garmin_data_p->serial_num 
@@ -1330,7 +1414,9 @@
 		   ignore it. */
 		dbg("%s - pkt ignored (%d)",
 			__FUNCTION__, garmin_data_p->ignorePkts);
+		spin_lock_irqsave(&garmin_data_p->lock, flags);
 		garmin_data_p->ignorePkts--;
+		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 	} else {
 		garmin_read_process(garmin_data_p, data, urb->actual_length);
 	}
@@ -1351,18 +1437,20 @@
  */
 static int garmin_flush_queue(struct garmin_data * garmin_data_p)
 {
+	unsigned long flags;
 	struct garmin_packet *pkt;
 
 	if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) {
 		pkt = pkt_pop(garmin_data_p);
 		if (pkt != NULL) {
-
 			send_to_tty(garmin_data_p->port, pkt->data, pkt->size);
 			kfree(pkt);
 			mod_timer(&garmin_data_p->timer, (1)+jiffies);
 
 		} else {
+			spin_lock_irqsave(&garmin_data_p->lock, flags);
 			garmin_data_p->flags &= ~FLAGS_QUEUING;
+			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 		}
 	}
 	return 0;
@@ -1371,26 +1459,41 @@
 
 static void garmin_throttle (struct usb_serial_port *port)
 {
+	unsigned long flags;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	/* set flag, data received will be put into a queue
 	   for later processing */
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 }
 
 
 static void garmin_unthrottle (struct usb_serial_port *port)
 {
+	unsigned long flags;
 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	int status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
+	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->flags &= ~FLAGS_THROTTLED;
+	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	/* in native mode send queued data to tty, in
 	   serial mode nothing needs to be done here */
 	if (garmin_data_p->mode == MODE_NATIVE)
 		garmin_flush_queue(garmin_data_p);
+
+	if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (status)
+			dev_err(&port->dev,
+				"%s - failed resubmitting read urb, error %d\n",
+				__FUNCTION__, status);
+	}
 }
 
 
@@ -1420,11 +1523,12 @@
 
 	dbg("%s", __FUNCTION__);
 
-	garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
+	garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
 	if (garmin_data_p == NULL) {
 		dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
 		return -ENOMEM;
 	}
+	memset (garmin_data_p, 0, sizeof(struct garmin_data));
 	init_timer(&garmin_data_p->timer);
 	spin_lock_init(&garmin_data_p->lock);
 	INIT_LIST_HEAD(&garmin_data_p->pktlist);
@@ -1459,10 +1563,10 @@
 /* All of the device info needed */
 static struct usb_serial_driver garmin_device = {
 	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"garmin_gps",
+		.owner       = THIS_MODULE,
+		.name        = "garmin_gps",
 	},
-	.description =		"Garmin GPS usb/tty",
+	.description         = "Garmin GPS usb/tty",
 	.id_table            = id_table,
 	.num_interrupt_in    = 1,
 	.num_bulk_in         = 1,
@@ -1483,6 +1587,7 @@
 };
 
 
+
 static int __init garmin_init (void)
 {
 	int retval;
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 1727135..21cbaa0 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -175,14 +175,14 @@
 
 	/* only do something if we have a bulk out endpoint */
 	if (serial->num_bulk_out) {
-		spin_lock(&port->lock);
+		spin_lock_bh(&port->lock);
 		if (port->write_urb_busy) {
-			spin_unlock(&port->lock);
+			spin_unlock_bh(&port->lock);
 			dbg("%s - already writing", __FUNCTION__);
 			return 0;
 		}
 		port->write_urb_busy = 1;
-		spin_unlock(&port->lock);
+		spin_unlock_bh(&port->lock);
 
 		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 9840bad..cbc725a 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -479,6 +479,7 @@
 	{ USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */
 	{ USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */
 	{ USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */
+	{ USB_DEVICE(0x0BB4, 0x0BCE) }, /* "High Tech Computer Corp" */
 	{ USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */
 	{ USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
 	{ USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */
@@ -652,11 +653,6 @@
 	port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
 	
 	msleep(1000*initial_wait);
-	/* Start reading from the device */
-	usb_fill_bulk_urb(port->read_urb, serial->dev, 
-		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      ipaq_read_bulk_callback, port);
 
 	/*
 	 * Send out control message observed in win98 sniffs. Not sure what
@@ -670,18 +666,31 @@
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
 				0x1, 0, NULL, 0, 100);
-		if (result == 0) {
-			result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-			if (result) {
-				err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
-				goto error;
-			}
-			return 0;
-		}
+		if (!result)
+			break;
+
 		msleep(1000);
 	}
-	err("%s - failed doing control urb, error %d", __FUNCTION__, result);
-	goto error;
+
+	if (!retries && result) {
+		err("%s - failed doing control urb, error %d", __FUNCTION__,
+		    result);
+		goto error;
+	}
+
+	/* Start reading from the device */
+	usb_fill_bulk_urb(port->read_urb, serial->dev,
+		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+		      ipaq_read_bulk_callback, port);
+
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (result) {
+		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+		goto error;
+	}
+
+	return 0;
 
 enomem:
 	result = -ENOMEM;
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 87306cb..812bc21 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -394,14 +394,14 @@
 		return 0;
 	}
 
-	spin_lock(&port->lock);
+	spin_lock_bh(&port->lock);
 	if (port->write_urb_busy) {
-		spin_unlock(&port->lock);
+		spin_unlock_bh(&port->lock);
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
 	}
 	port->write_urb_busy = 1;
-	spin_unlock(&port->lock);
+	spin_unlock_bh(&port->lock);
 
 	count = min(count, port->bulk_out_size);
 	memcpy(port->bulk_out_buffer, buf, count);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 1738b0b..1b348df 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -342,14 +342,14 @@
 	if (count == 0)
 		return 0;
 
-	spin_lock(&port->lock);
+	spin_lock_bh(&port->lock);
 	if (port->write_urb_busy) {
-		spin_unlock(&port->lock);
+		spin_unlock_bh(&port->lock);
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
 	}
 	port->write_urb_busy = 1;
-	spin_unlock(&port->lock);
+	spin_unlock_bh(&port->lock);
 
 	transfer_buffer = port->write_urb->transfer_buffer;
 	transfer_size = min(count, port->bulk_out_size - 1);
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 49b8dc0..59e777f 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -518,13 +518,13 @@
 	   the TX urb is in-flight (wait until it completes)
 	   the device is full (wait until it says there is room)
 	*/
-	spin_lock(&port->lock);
+	spin_lock_bh(&port->lock);
 	if (port->write_urb_busy || priv->tx_throttled) {
-		spin_unlock(&port->lock);
+		spin_unlock_bh(&port->lock);
 		return 0;
 	}
 	port->write_urb_busy = 1;
-	spin_unlock(&port->lock);
+	spin_unlock_bh(&port->lock);
 
 	/* At this point the URB is in our control, nobody else can submit it
 	   again (the only sudden transition was the one from EINPROGRESS to
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
new file mode 100644
index 0000000..95bf571
--- /dev/null
+++ b/drivers/usb/serial/mos7840.c
@@ -0,0 +1,2962 @@
+/*
+ * 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
+ *
+ * Clean ups from Moschip version and a few ioctl implementations by:
+ *	Paul B Schroeder <pschroeder "at" uplogix "dot" com>
+ *
+ * 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/serial.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.3.1"
+#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
+
+/*
+ * 16C50 UART register defines
+ */
+
+#define LCR_BITS_5             0x00	/* 5 bits/char */
+#define LCR_BITS_6             0x01	/* 6 bits/char */
+#define LCR_BITS_7             0x02	/* 7 bits/char */
+#define LCR_BITS_8             0x03	/* 8 bits/char */
+#define LCR_BITS_MASK          0x03	/* Mask for bits/char field */
+
+#define LCR_STOP_1             0x00	/* 1 stop bit */
+#define LCR_STOP_1_5           0x04	/* 1.5 stop bits (if 5   bits/char) */
+#define LCR_STOP_2             0x04	/* 2 stop bits   (if 6-8 bits/char) */
+#define LCR_STOP_MASK          0x04	/* Mask for stop bits field */
+
+#define LCR_PAR_NONE           0x00	/* No parity */
+#define LCR_PAR_ODD            0x08	/* Odd parity */
+#define LCR_PAR_EVEN           0x18	/* Even parity */
+#define LCR_PAR_MARK           0x28	/* Force parity bit to 1 */
+#define LCR_PAR_SPACE          0x38	/* Force parity bit to 0 */
+#define LCR_PAR_MASK           0x38	/* Mask for parity field */
+
+#define LCR_SET_BREAK          0x40	/* Set Break condition */
+#define LCR_DL_ENABLE          0x80	/* Enable access to divisor latch */
+
+#define MCR_DTR                0x01	/* Assert DTR */
+#define MCR_RTS                0x02	/* Assert RTS */
+#define MCR_OUT1               0x04	/* Loopback only: Sets state of RI */
+#define MCR_MASTER_IE          0x08	/* Enable interrupt outputs */
+#define MCR_LOOPBACK           0x10	/* Set internal (digital) loopback mode */
+#define MCR_XON_ANY            0x20	/* Enable any char to exit XOFF mode */
+
+#define MOS7840_MSR_CTS        0x10	/* Current state of CTS */
+#define MOS7840_MSR_DSR        0x20	/* Current state of DSR */
+#define MOS7840_MSR_RI         0x40	/* Current state of RI */
+#define MOS7840_MSR_CD         0x80	/* Current state of CD */
+
+/*
+ * Defines used for sending commands to port
+ */
+
+#define WAIT_FOR_EVER   (HZ * 0 )	/* timeout urb is wait for ever */
+#define MOS_WDR_TIMEOUT (HZ * 5 )	/* default urb timeout */
+
+#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
+
+/* Requests */
+#define MCS_RD_RTYPE    0xC0
+#define MCS_WR_RTYPE    0x40
+#define MCS_RDREQ       0x0D
+#define MCS_WRREQ       0x0E
+#define MCS_CTRL_TIMEOUT        500
+#define VENDOR_READ_LENGTH      (0x01)
+
+#define MAX_NAME_LEN    64
+
+#define ZLP_REG1  0x3A		//Zero_Flag_Reg1    58
+#define ZLP_REG5  0x3E		//Zero_Flag_Reg5    62
+
+/* For higher baud Rates use TIOCEXBAUD */
+#define TIOCEXBAUD     0x5462
+
+/* vendor id and device id defines */
+
+#define USB_VENDOR_ID_MOSCHIP           0x9710
+#define MOSCHIP_DEVICE_ID_7840          0x7840
+#define MOSCHIP_DEVICE_ID_7820          0x7820
+
+/* Interrupt Rotinue Defines    */
+
+#define SERIAL_IIR_RLS      0x06
+#define SERIAL_IIR_MS       0x00
+
+/*
+ *  Emulation of the bit mask on the LINE STATUS REGISTER.
+ */
+#define SERIAL_LSR_DR       0x0001
+#define SERIAL_LSR_OE       0x0002
+#define SERIAL_LSR_PE       0x0004
+#define SERIAL_LSR_FE       0x0008
+#define SERIAL_LSR_BI       0x0010
+
+#define MOS_MSR_DELTA_CTS   0x10
+#define MOS_MSR_DELTA_DSR   0x20
+#define MOS_MSR_DELTA_RI    0x40
+#define MOS_MSR_DELTA_CD    0x80
+
+// Serial Port register Address
+#define INTERRUPT_ENABLE_REGISTER  ((__u16)(0x01))
+#define FIFO_CONTROL_REGISTER      ((__u16)(0x02))
+#define LINE_CONTROL_REGISTER      ((__u16)(0x03))
+#define MODEM_CONTROL_REGISTER     ((__u16)(0x04))
+#define LINE_STATUS_REGISTER       ((__u16)(0x05))
+#define MODEM_STATUS_REGISTER      ((__u16)(0x06))
+#define SCRATCH_PAD_REGISTER       ((__u16)(0x07))
+#define DIVISOR_LATCH_LSB          ((__u16)(0x00))
+#define DIVISOR_LATCH_MSB          ((__u16)(0x01))
+
+#define CLK_MULTI_REGISTER         ((__u16)(0x02))
+#define CLK_START_VALUE_REGISTER   ((__u16)(0x03))
+
+#define SERIAL_LCR_DLAB            ((__u16)(0x0080))
+
+/*
+ * URB POOL related defines
+ */
+#define NUM_URBS                        16	/* URB Count */
+#define URB_TRANSFER_BUFFER_SIZE        32	/* URB Size  */
+
+
+static struct usb_device_id moschip_port_id_table[] = {
+	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
+	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+	{}			/* terminating entry */
+};
+
+static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
+	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
+	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+	{}			/* terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, moschip_id_table_combined);
+
+/* This structure holds all of the local port information */
+
+struct moschip_port {
+	int port_num;		/*Actual port number in the device(1,2,etc) */
+	struct urb *write_urb;	/* write URB for this port */
+	struct urb *read_urb;	/* read URB for this port */
+	__u8 shadowLCR;		/* last LCR value received */
+	__u8 shadowMCR;		/* last MCR value received */
+	char open;
+	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */
+	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */
+	int delta_msr_cond;
+	struct async_icount icount;
+	struct usb_serial_port *port;	/* loop back to the owner of this object */
+
+	/*Offsets */
+	__u8 SpRegOffset;
+	__u8 ControlRegOffset;
+	__u8 DcrRegOffset;
+	//for processing control URBS in interrupt context
+	struct urb *control_urb;
+	char *ctrl_buf;
+	int MsrLsr;
+
+	struct urb *write_urb_pool[NUM_URBS];
+};
+
+
+static int debug;
+static int mos7840_num_ports;	//this says the number of ports in the device
+static int mos7840_num_open_ports;
+
+
+/*
+ * mos7840_set_reg_sync
+ * 	To set the Control register by calling usb_fill_control_urb function
+ *	by passing usb_sndctrlpipe function as parameter.
+ */
+
+static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,
+				__u16 val)
+{
+	struct usb_device *dev = port->serial->dev;
+	val = val & 0x00ff;
+	dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val);
+
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+			       MCS_WR_RTYPE, val, reg, NULL, 0,
+			       MOS_WDR_TIMEOUT);
+}
+
+/*
+ * mos7840_get_reg_sync
+ * 	To set the Uart register by calling usb_fill_control_urb function by
+ *	passing usb_rcvctrlpipe function as parameter.
+ */
+
+static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
+				__u16 * val)
+{
+	struct usb_device *dev = port->serial->dev;
+	int ret = 0;
+
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+			      MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,
+			      MOS_WDR_TIMEOUT);
+	dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val);
+	*val = (*val) & 0x00ff;
+	return ret;
+}
+
+/*
+ * mos7840_set_uart_reg
+ *	To set the Uart register by calling usb_fill_control_urb function by
+ *	passing usb_sndctrlpipe function as parameter.
+ */
+
+static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
+				__u16 val)
+{
+
+	struct usb_device *dev = port->serial->dev;
+	val = val & 0x00ff;
+	// For the UART control registers, the application number need to be Or'ed
+	if (mos7840_num_ports == 4) {
+		val |=
+		    (((__u16) port->number - (__u16) (port->serial->minor)) +
+		     1) << 8;
+		dbg("mos7840_set_uart_reg application number is %x\n", val);
+	} else {
+		if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
+			val |=
+			    (((__u16) port->number -
+			      (__u16) (port->serial->minor)) + 1) << 8;
+			dbg("mos7840_set_uart_reg application number is %x\n",
+			    val);
+		} else {
+			val |=
+			    (((__u16) port->number -
+			      (__u16) (port->serial->minor)) + 2) << 8;
+			dbg("mos7840_set_uart_reg application number is %x\n",
+			    val);
+		}
+	}
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+			       MCS_WR_RTYPE, val, reg, NULL, 0,
+			       MOS_WDR_TIMEOUT);
+
+}
+
+/*
+ * mos7840_get_uart_reg
+ *	To set the Control register by calling usb_fill_control_urb function
+ *	by passing usb_rcvctrlpipe function as parameter.
+ */
+static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
+				__u16 * val)
+{
+	struct usb_device *dev = port->serial->dev;
+	int ret = 0;
+	__u16 Wval;
+
+	//dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
+	/*Wval  is same as application number */
+	if (mos7840_num_ports == 4) {
+		Wval =
+		    (((__u16) port->number - (__u16) (port->serial->minor)) +
+		     1) << 8;
+		dbg("mos7840_get_uart_reg application number is %x\n", Wval);
+	} else {
+		if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
+			Wval =
+			    (((__u16) port->number -
+			      (__u16) (port->serial->minor)) + 1) << 8;
+			dbg("mos7840_get_uart_reg application number is %x\n",
+			    Wval);
+		} else {
+			Wval =
+			    (((__u16) port->number -
+			      (__u16) (port->serial->minor)) + 2) << 8;
+			dbg("mos7840_get_uart_reg application number is %x\n",
+			    Wval);
+		}
+	}
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+			      MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH,
+			      MOS_WDR_TIMEOUT);
+	*val = (*val) & 0x00ff;
+	return ret;
+}
+
+static void mos7840_dump_serial_port(struct moschip_port *mos7840_port)
+{
+
+	dbg("***************************************\n");
+	dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset);
+	dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset);
+	dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset);
+	dbg("***************************************\n");
+
+}
+
+/************************************************************************/
+/************************************************************************/
+/*             I N T E R F A C E   F U N C T I O N S			*/
+/*             I N T E R F A C E   F U N C T I O N S			*/
+/************************************************************************/
+/************************************************************************/
+
+static inline void mos7840_set_port_private(struct usb_serial_port *port,
+					    struct moschip_port *data)
+{
+	usb_set_serial_port_data(port, (void *)data);
+}
+
+static inline struct moschip_port *mos7840_get_port_private(struct
+							    usb_serial_port
+							    *port)
+{
+	return (struct moschip_port *)usb_get_serial_port_data(port);
+}
+
+static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
+{
+	struct moschip_port *mos7840_port;
+	struct async_icount *icount;
+	mos7840_port = port;
+	icount = &mos7840_port->icount;
+	if (new_msr &
+	    (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
+	     MOS_MSR_DELTA_CD)) {
+		icount = &mos7840_port->icount;
+
+		/* update input line counters */
+		if (new_msr & MOS_MSR_DELTA_CTS) {
+			icount->cts++;
+		}
+		if (new_msr & MOS_MSR_DELTA_DSR) {
+			icount->dsr++;
+		}
+		if (new_msr & MOS_MSR_DELTA_CD) {
+			icount->dcd++;
+		}
+		if (new_msr & MOS_MSR_DELTA_RI) {
+			icount->rng++;
+		}
+	}
+
+	return 0;
+}
+
+static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
+{
+	struct async_icount *icount;
+
+	dbg("%s - %02x", __FUNCTION__, new_lsr);
+
+	if (new_lsr & SERIAL_LSR_BI) {
+		//
+		// Parity and Framing errors only count if they
+		// occur exclusive of a break being
+		// received.
+		//
+		new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
+	}
+
+	/* update input line counters */
+	icount = &port->icount;
+	if (new_lsr & SERIAL_LSR_BI) {
+		icount->brk++;
+	}
+	if (new_lsr & SERIAL_LSR_OE) {
+		icount->overrun++;
+	}
+	if (new_lsr & SERIAL_LSR_PE) {
+		icount->parity++;
+	}
+	if (new_lsr & SERIAL_LSR_FE) {
+		icount->frame++;
+	}
+
+	return 0;
+}
+
+/************************************************************************/
+/************************************************************************/
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/************************************************************************/
+/************************************************************************/
+
+static void mos7840_control_callback(struct urb *urb, struct pt_regs *regs)
+{
+	unsigned char *data;
+	struct moschip_port *mos7840_port;
+	__u8 regval = 0x0;
+
+	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;
+	}
+
+	mos7840_port = (struct moschip_port *)urb->context;
+
+	dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
+	dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
+	    mos7840_port->MsrLsr, mos7840_port->port_num);
+	data = urb->transfer_buffer;
+	regval = (__u8) data[0];
+	dbg("%s data is %x\n", __FUNCTION__, regval);
+	if (mos7840_port->MsrLsr == 0)
+		mos7840_handle_new_msr(mos7840_port, regval);
+	else if (mos7840_port->MsrLsr == 1)
+		mos7840_handle_new_lsr(mos7840_port, regval);
+
+      exit:
+	return;
+}
+
+static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
+			   __u16 * val)
+{
+	struct usb_device *dev = mcs->port->serial->dev;
+	struct usb_ctrlrequest *dr = NULL;
+	unsigned char *buffer = NULL;
+	int ret = 0;
+	buffer = (__u8 *) mcs->ctrl_buf;
+
+//      dr=(struct usb_ctrlrequest *)(buffer);
+	dr = (void *)(buffer + 2);
+	dr->bRequestType = MCS_RD_RTYPE;
+	dr->bRequest = MCS_RDREQ;
+	dr->wValue = cpu_to_le16(Wval);	//0;
+	dr->wIndex = cpu_to_le16(reg);
+	dr->wLength = cpu_to_le16(2);
+
+	usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0),
+			     (unsigned char *)dr, buffer, 2,
+			     mos7840_control_callback, mcs);
+	mcs->control_urb->transfer_buffer_length = 2;
+	ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+	return ret;
+}
+
+/*****************************************************************************
+ * mos7840_interrupt_callback
+ *	this is the callback function for when we have received data on the
+ *	interrupt endpoint.
+ *****************************************************************************/
+
+static void mos7840_interrupt_callback(struct urb *urb, struct pt_regs *regs)
+{
+	int result;
+	int length;
+	struct moschip_port *mos7840_port;
+	struct usb_serial *serial;
+	__u16 Data;
+	unsigned char *data;
+	__u8 sp[5], st;
+	int i;
+	__u16 wval;
+
+	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;
+
+	serial = (struct usb_serial *)urb->context;
+
+	/* Moschip get 5 bytes
+	 * Byte 1 IIR Port 1 (port.number is 0)
+	 * Byte 2 IIR Port 2 (port.number is 1)
+	 * Byte 3 IIR Port 3 (port.number is 2)
+	 * Byte 4 IIR Port 4 (port.number is 3)
+	 * Byte 5 FIFO status for both */
+
+	if (length && length > 5) {
+		dbg("%s \n", "Wrong data !!!");
+		return;
+	}
+
+	sp[0] = (__u8) data[0];
+	sp[1] = (__u8) data[1];
+	sp[2] = (__u8) data[2];
+	sp[3] = (__u8) data[3];
+	st = (__u8) data[4];
+
+	for (i = 0; i < serial->num_ports; i++) {
+		mos7840_port = mos7840_get_port_private(serial->port[i]);
+		wval =
+		    (((__u16) serial->port[i]->number -
+		      (__u16) (serial->minor)) + 1) << 8;
+		if (mos7840_port->open) {
+			if (sp[i] & 0x01) {
+				dbg("SP%d No Interrupt !!!\n", i);
+			} else {
+				switch (sp[i] & 0x0f) {
+				case SERIAL_IIR_RLS:
+					dbg("Serial Port %d: Receiver status error or ", i);
+					dbg("address bit detected in 9-bit mode\n");
+					mos7840_port->MsrLsr = 1;
+					mos7840_get_reg(mos7840_port, wval,
+							LINE_STATUS_REGISTER,
+							&Data);
+					break;
+				case SERIAL_IIR_MS:
+					dbg("Serial Port %d: Modem status change\n", i);
+					mos7840_port->MsrLsr = 0;
+					mos7840_get_reg(mos7840_port, wval,
+							MODEM_STATUS_REGISTER,
+							&Data);
+					break;
+				}
+			}
+		}
+	}
+      exit:
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result) {
+		dev_err(&urb->dev->dev,
+			"%s - Error %d submitting interrupt urb\n",
+			__FUNCTION__, result);
+	}
+
+	return;
+
+}
+
+static int mos7840_port_paranoia_check(struct usb_serial_port *port,
+				       const char *function)
+{
+	if (!port) {
+		dbg("%s - port == NULL", function);
+		return -1;
+	}
+	if (!port->serial) {
+		dbg("%s - port->serial == NULL", function);
+		return -1;
+	}
+
+	return 0;
+}
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static int mos7840_serial_paranoia_check(struct usb_serial *serial,
+					 const char *function)
+{
+	if (!serial) {
+		dbg("%s - serial == NULL", function);
+		return -1;
+	}
+	if (!serial->type) {
+		dbg("%s - serial->type == NULL!", function);
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
+						 const char *function)
+{
+	/* if no port was specified, or it fails a paranoia check */
+	if (!port ||
+	    mos7840_port_paranoia_check(port, function) ||
+	    mos7840_serial_paranoia_check(port->serial, function)) {
+		/* then say that we don't have a valid usb_serial thing, which will                  * end up genrating -ENODEV return values */
+		return NULL;
+	}
+
+	return port->serial;
+}
+
+/*****************************************************************************
+ * mos7840_bulk_in_callback
+ *	this is the callback function for when we have received data on the
+ *	bulk in endpoint.
+ *****************************************************************************/
+
+static void mos7840_bulk_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+	int status;
+	unsigned char *data;
+	struct usb_serial *serial;
+	struct usb_serial_port *port;
+	struct moschip_port *mos7840_port;
+	struct tty_struct *tty;
+
+	if (!urb) {
+		dbg("%s", "Invalid Pointer !!!!:\n");
+		return;
+	}
+
+	if (urb->status) {
+		dbg("nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+
+	mos7840_port = (struct moschip_port *)urb->context;
+	if (!mos7840_port) {
+		dbg("%s", "NULL mos7840_port pointer \n");
+		return;
+	}
+
+	port = (struct usb_serial_port *)mos7840_port->port;
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Port Paranoia failed \n");
+		return;
+	}
+
+	serial = mos7840_get_usb_serial(port, __FUNCTION__);
+	if (!serial) {
+		dbg("%s\n", "Bad serial pointer ");
+		return;
+	}
+
+	dbg("%s\n", "Entering... \n");
+
+	data = urb->transfer_buffer;
+
+	dbg("%s", "Entering ........... \n");
+
+	if (urb->actual_length) {
+		tty = mos7840_port->port->tty;
+		if (tty) {
+			tty_buffer_request_room(tty, urb->actual_length);
+			tty_insert_flip_string(tty, data, urb->actual_length);
+			dbg(" %s \n", data);
+			tty_flip_buffer_push(tty);
+		}
+		mos7840_port->icount.rx += urb->actual_length;
+		dbg("mos7840_port->icount.rx is %d:\n",
+		    mos7840_port->icount.rx);
+	}
+
+	if (!mos7840_port->read_urb) {
+		dbg("%s", "URB KILLED !!!\n");
+		return;
+	}
+
+	if (mos7840_port->read_urb->status != -EINPROGRESS) {
+		mos7840_port->read_urb->dev = serial->dev;
+
+		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+
+		if (status) {
+			dbg(" usb_submit_urb(read bulk) failed, status = %d",
+			    status);
+		}
+	}
+}
+
+/*****************************************************************************
+ * mos7840_bulk_out_data_callback
+ *	this is the callback function for when we have finished sending serial data
+ *	on the bulk out endpoint.
+ *****************************************************************************/
+
+static void mos7840_bulk_out_data_callback(struct urb *urb,
+					   struct pt_regs *regs)
+{
+	struct moschip_port *mos7840_port;
+	struct tty_struct *tty;
+	if (!urb) {
+		dbg("%s", "Invalid Pointer !!!!:\n");
+		return;
+	}
+
+	if (urb->status) {
+		dbg("nonzero write bulk status received:%d\n", urb->status);
+		return;
+	}
+
+	mos7840_port = (struct moschip_port *)urb->context;
+	if (!mos7840_port) {
+		dbg("%s", "NULL mos7840_port pointer \n");
+		return;
+	}
+
+	if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
+		dbg("%s", "Port Paranoia failed \n");
+		return;
+	}
+
+	dbg("%s \n", "Entering .........");
+
+	tty = mos7840_port->port->tty;
+
+	if (tty && mos7840_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);
+	}
+
+}
+
+/************************************************************************/
+/*       D R I V E R  T T Y  I N T E R F A C E  F U N C T I O N S       */
+/************************************************************************/
+#ifdef MCSSerialProbe
+static int mos7840_serial_probe(struct usb_serial *serial,
+				const struct usb_device_id *id)
+{
+
+	/*need to implement the mode_reg reading and updating\
+	   structures usb_serial_ device_type\
+	   (i.e num_ports, num_bulkin,bulkout etc) */
+	/* Also we can update the changes  attach */
+	return 1;
+}
+#endif
+
+/*****************************************************************************
+ * mos7840_open
+ *	this function is called by the tty driver when a port is opened
+ *	If successful, we return 0
+ *	Otherwise we return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+{
+	int response;
+	int j;
+	struct usb_serial *serial;
+	struct urb *urb;
+	__u16 Data;
+	int status;
+	struct moschip_port *mos7840_port;
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Port Paranoia failed \n");
+		return -ENODEV;
+	}
+
+	mos7840_num_open_ports++;
+	serial = port->serial;
+
+	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+		dbg("%s", "Serial Paranoia failed \n");
+		return -ENODEV;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+
+	if (mos7840_port == 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);
+		mos7840_port->write_urb_pool[j] = urb;
+
+		if (urb == NULL) {
+			err("No more urbs???");
+			continue;
+		}
+
+		urb->transfer_buffer = NULL;
+		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 MCS7840 -- Write Init values to corresponding Registers
+ *
+ * Register Index
+ * 1 : IER
+ * 2 : FCR
+ * 3 : LCR
+ * 4 : MCR
+ *
+ * 0x08 : SP1/2 Control Reg
+ *****************************************************************************/
+
+//NEED to check the following Block
+
+	status = 0;
+	Data = 0x0;
+	status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
+	if (status < 0) {
+		dbg("Reading Spreg failed\n");
+		return -1;
+	}
+	Data |= 0x80;
+	status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+	if (status < 0) {
+		dbg("writing Spreg failed\n");
+		return -1;
+	}
+
+	Data &= ~0x80;
+	status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+	if (status < 0) {
+		dbg("writing Spreg failed\n");
+		return -1;
+	}
+//End of block to be checked
+
+	status = 0;
+	Data = 0x0;
+	status =
+	    mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+	if (status < 0) {
+		dbg("Reading Controlreg failed\n");
+		return -1;
+	}
+	Data |= 0x08;		//Driver done bit
+	Data |= 0x20;		//rx_disable
+	status = 0;
+	status =
+	    mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+	if (status < 0) {
+		dbg("writing Controlreg failed\n");
+		return -1;
+	}
+	//do register settings here
+	// Set all regs to the device default values.
+	////////////////////////////////////
+	// First Disable all interrupts.
+	////////////////////////////////////
+
+	Data = 0x00;
+	status = 0;
+	status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+	if (status < 0) {
+		dbg("disableing interrupts failed\n");
+		return -1;
+	}
+	// Set FIFO_CONTROL_REGISTER to the default value
+	Data = 0x00;
+	status = 0;
+	status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+	if (status < 0) {
+		dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
+		return -1;
+	}
+
+	Data = 0xcf;
+	status = 0;
+	status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+	if (status < 0) {
+		dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
+		return -1;
+	}
+
+	Data = 0x03;
+	status = 0;
+	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+	mos7840_port->shadowLCR = Data;
+
+	Data = 0x0b;
+	status = 0;
+	status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+	mos7840_port->shadowMCR = Data;
+
+	Data = 0x00;
+	status = 0;
+	status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+	mos7840_port->shadowLCR = Data;
+
+	Data |= SERIAL_LCR_DLAB;	//data latch enable in LCR 0x80
+	status = 0;
+	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+	Data = 0x0c;
+	status = 0;
+	status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
+
+	Data = 0x0;
+	status = 0;
+	status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
+
+	Data = 0x00;
+	status = 0;
+	status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+
+	Data = Data & ~SERIAL_LCR_DLAB;
+	status = 0;
+	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+	mos7840_port->shadowLCR = Data;
+
+	//clearing Bulkin and Bulkout Fifo
+	Data = 0x0;
+	status = 0;
+	status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
+
+	Data = Data | 0x0c;
+	status = 0;
+	status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+
+	Data = Data & ~0x0c;
+	status = 0;
+	status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+	//Finally enable all interrupts
+	Data = 0x0;
+	Data = 0x0c;
+	status = 0;
+	status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+	//clearing rx_disable
+	Data = 0x0;
+	status = 0;
+	status =
+	    mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+	Data = Data & ~0x20;
+	status = 0;
+	status =
+	    mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+
+	// rx_negate
+	Data = 0x0;
+	status = 0;
+	status =
+	    mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+	Data = Data | 0x10;
+	status = 0;
+	status =
+	    mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+
+	/* 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;
+/* Check to see if we've set up our endpoint info yet    *
+     * (can't set it up in mos7840_startup as the structures *
+     * were not set up at that time.)                        */
+	if (mos7840_num_open_ports == 1) {
+		if (serial->port[0]->interrupt_in_buffer == NULL) {
+
+			/* set up interrupt urb */
+
+			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
+					 serial->dev,
+					 usb_rcvintpipe(serial->dev,
+							serial->port[0]->
+							interrupt_in_endpointAddress),
+					 serial->port[0]->interrupt_in_buffer,
+					 serial->port[0]->interrupt_in_urb->
+					 transfer_buffer_length,
+					 mos7840_interrupt_callback,
+					 serial,
+					 serial->port[0]->interrupt_in_urb->
+					 interval);
+
+			/* start interrupt read for mos7840               *
+			 * will continue as long as mos7840 is connected  */
+
+			response =
+			    usb_submit_urb(serial->port[0]->interrupt_in_urb,
+					   GFP_KERNEL);
+			if (response) {
+				err("%s - Error %d submitting interrupt urb",
+				    __FUNCTION__, response);
+			}
+
+		}
+
+	}
+
+	/* see if we've set up our endpoint info yet   *
+	 * (can't set it up in mos7840_startup as the  *
+	 * structures were not set up at that time.)   */
+
+	dbg("port number is %d \n", port->number);
+	dbg("serial number is %d \n", port->serial->minor);
+	dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress);
+	dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress);
+	dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress);
+	dbg("port's number in the device is %d\n", mos7840_port->port_num);
+	mos7840_port->read_urb = port->read_urb;
+
+	/* set up our bulk in urb */
+
+	usb_fill_bulk_urb(mos7840_port->read_urb,
+			  serial->dev,
+			  usb_rcvbulkpipe(serial->dev,
+					  port->bulk_in_endpointAddress),
+			  port->bulk_in_buffer,
+			  mos7840_port->read_urb->transfer_buffer_length,
+			  mos7840_bulk_in_callback, mos7840_port);
+
+	dbg("mos7840_open: bulkin endpoint is %d\n",
+	    port->bulk_in_endpointAddress);
+	response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
+	if (response) {
+		err("%s - Error %d submitting control urb", __FUNCTION__,
+		    response);
+	}
+
+	/* initialize our wait queues */
+	init_waitqueue_head(&mos7840_port->wait_chase);
+	init_waitqueue_head(&mos7840_port->delta_msr_wait);
+
+	/* initialize our icount structure */
+	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
+
+	/* initialize our port settings */
+	mos7840_port->shadowMCR = MCR_MASTER_IE;	/* Must set to enable ints! */
+	/* send a open port command */
+	mos7840_port->open = 1;
+	//mos7840_change_port_settings(mos7840_port,old_termios);
+	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);
+
+	return 0;
+
+}
+
+/*****************************************************************************
+ * mos7840_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 mos7840_chars_in_buffer(struct usb_serial_port *port)
+{
+	int i;
+	int chars = 0;
+	struct moschip_port *mos7840_port;
+
+	dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return -1;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+	if (mos7840_port == NULL) {
+		dbg("%s \n", "mos7840_break:leaving ...........");
+		return -1;
+	}
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (mos7840_port->write_urb_pool[i]->status == -EINPROGRESS) {
+			chars += URB_TRANSFER_BUFFER_SIZE;
+		}
+	}
+	dbg("%s - returns %d", __FUNCTION__, chars);
+	return (chars);
+
+}
+
+/************************************************************************
+ *
+ * mos7840_block_until_tx_empty
+ *
+ *	This function will block the close until one of the following:
+ *		1. TX count are 0
+ *		2. The mos7840 has stopped
+ *		3. A timout of 3 seconds without activity has expired
+ *
+ ************************************************************************/
+static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+{
+	int timeout = HZ / 10;
+	int wait = 30;
+	int count;
+
+	while (1) {
+
+		count = mos7840_chars_in_buffer(mos7840_port->port);
+
+		/* Check for Buffer status */
+		if (count <= 0) {
+			return;
+		}
+
+		/* Block the thread for a while */
+		interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
+					       timeout);
+
+		/* No activity.. count down section */
+		wait--;
+		if (wait == 0) {
+			dbg("%s - TIMEOUT", __FUNCTION__);
+			return;
+		} else {
+			/* Reset timout value back to seconds */
+			wait = 30;
+		}
+	}
+}
+
+/*****************************************************************************
+ * mos7840_close
+ *	this function is called by the tty driver when a port is closed
+ *****************************************************************************/
+
+static void mos7840_close(struct usb_serial_port *port, struct file *filp)
+{
+	struct usb_serial *serial;
+	struct moschip_port *mos7840_port;
+	int j;
+	__u16 Data;
+
+	dbg("%s\n", "mos7840_close:entering...");
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Port Paranoia failed \n");
+		return;
+	}
+
+	serial = mos7840_get_usb_serial(port, __FUNCTION__);
+	if (!serial) {
+		dbg("%s", "Serial Paranoia failed \n");
+		return;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+
+	if (mos7840_port == NULL) {
+		return;
+	}
+
+	for (j = 0; j < NUM_URBS; ++j)
+		usb_kill_urb(mos7840_port->write_urb_pool[j]);
+
+	/* Freeing Write URBs */
+	for (j = 0; j < NUM_URBS; ++j) {
+		if (mos7840_port->write_urb_pool[j]) {
+			if (mos7840_port->write_urb_pool[j]->transfer_buffer)
+				kfree(mos7840_port->write_urb_pool[j]->
+				      transfer_buffer);
+
+			usb_free_urb(mos7840_port->write_urb_pool[j]);
+		}
+	}
+
+	if (serial->dev) {
+		/* flush and block until tx is empty */
+		mos7840_block_until_tx_empty(mos7840_port);
+	}
+
+	/* While closing port, shutdown all bulk read, write  *
+	 * and interrupt read if they exists                  */
+	if (serial->dev) {
+
+		if (mos7840_port->write_urb) {
+			dbg("%s", "Shutdown bulk write\n");
+			usb_kill_urb(mos7840_port->write_urb);
+		}
+
+		if (mos7840_port->read_urb) {
+			dbg("%s", "Shutdown bulk read\n");
+			usb_kill_urb(mos7840_port->read_urb);
+		}
+		if ((&mos7840_port->control_urb)) {
+			dbg("%s", "Shutdown control read\n");
+			//      usb_kill_urb (mos7840_port->control_urb);
+
+		}
+	}
+//              if(mos7840_port->ctrl_buf != NULL)
+//                      kfree(mos7840_port->ctrl_buf);
+	mos7840_num_open_ports--;
+	dbg("mos7840_num_open_ports in close%d:in port%d\n",
+	    mos7840_num_open_ports, port->number);
+	if (mos7840_num_open_ports == 0) {
+		if (serial->port[0]->interrupt_in_urb) {
+			dbg("%s", "Shutdown interrupt_in_urb\n");
+		}
+	}
+
+	if (mos7840_port->write_urb) {
+		/* if this urb had a transfer buffer already (old tx) free it */
+
+		if (mos7840_port->write_urb->transfer_buffer != NULL) {
+			kfree(mos7840_port->write_urb->transfer_buffer);
+		}
+		usb_free_urb(mos7840_port->write_urb);
+	}
+
+	Data = 0x0;
+	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+	Data = 0x00;
+	mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+	mos7840_port->open = 0;
+
+	dbg("%s \n", "Leaving ............");
+}
+
+/************************************************************************
+ *
+ * mos7840_block_until_chase_response
+ *
+ *	This function will block the close until one of the following:
+ *		1. Response to our Chase comes from mos7840
+ *		2. A timout of 10 seconds without activity has expired
+ *		   (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
+ *
+ ************************************************************************/
+
+static void mos7840_block_until_chase_response(struct moschip_port
+					       *mos7840_port)
+{
+	int timeout = 1 * HZ;
+	int wait = 10;
+	int count;
+
+	while (1) {
+		count = mos7840_chars_in_buffer(mos7840_port->port);
+
+		/* Check for Buffer status */
+		if (count <= 0) {
+			return;
+		}
+
+		/* Block the thread for a while */
+		interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
+					       timeout);
+		/* No activity.. count down section */
+		wait--;
+		if (wait == 0) {
+			dbg("%s - TIMEOUT", __FUNCTION__);
+			return;
+		} else {
+			/* Reset timout value back to seconds */
+			wait = 10;
+		}
+	}
+
+}
+
+/*****************************************************************************
+ * mos7840_break
+ *	this function sends a break to the port
+ *****************************************************************************/
+static void mos7840_break(struct usb_serial_port *port, int break_state)
+{
+	unsigned char data;
+	struct usb_serial *serial;
+	struct moschip_port *mos7840_port;
+
+	dbg("%s \n", "Entering ...........");
+	dbg("mos7840_break: Start\n");
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Port Paranoia failed \n");
+		return;
+	}
+
+	serial = mos7840_get_usb_serial(port, __FUNCTION__);
+	if (!serial) {
+		dbg("%s", "Serial Paranoia failed \n");
+		return;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+
+	if (mos7840_port == NULL) {
+		return;
+	}
+
+	if (serial->dev) {
+
+		/* flush and block until tx is empty */
+		mos7840_block_until_chase_response(mos7840_port);
+	}
+
+	if (break_state == -1) {
+		data = mos7840_port->shadowLCR | LCR_SET_BREAK;
+	} else {
+		data = mos7840_port->shadowLCR & ~LCR_SET_BREAK;
+	}
+
+	mos7840_port->shadowLCR = data;
+	dbg("mcs7840_break mos7840_port->shadowLCR is %x\n",
+	    mos7840_port->shadowLCR);
+	mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER,
+			     mos7840_port->shadowLCR);
+
+	return;
+}
+
+/*****************************************************************************
+ * mos7840_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 mos7840_write_room(struct usb_serial_port *port)
+{
+	int i;
+	int room = 0;
+	struct moschip_port *mos7840_port;
+
+	dbg("%s \n", " mos7840_write_room:entering ...........");
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		dbg("%s \n", " mos7840_write_room:leaving ...........");
+		return -1;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+	if (mos7840_port == NULL) {
+		dbg("%s \n", "mos7840_break:leaving ...........");
+		return -1;
+	}
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+			room += URB_TRANSFER_BUFFER_SIZE;
+		}
+	}
+
+	dbg("%s - returns %d", __FUNCTION__, room);
+	return (room);
+
+}
+
+/*****************************************************************************
+ * mos7840_write
+ *	this function is called by the tty driver when data should be written to
+ *	the port.
+ *	If successful, we return the number of bytes written, otherwise we
+ *      return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_write(struct usb_serial_port *port,
+			 const unsigned char *data, int count)
+{
+	int status;
+	int i;
+	int bytes_sent = 0;
+	int transfer_size;
+	int from_user = 0;
+
+	struct moschip_port *mos7840_port;
+	struct usb_serial *serial;
+	struct urb *urb;
+	//__u16 Data;
+	const unsigned char *current_position = data;
+	unsigned char *data1;
+	dbg("%s \n", "entering ...........");
+	//dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR);
+
+#ifdef NOTMOS7840
+	Data = 0x00;
+	status = 0;
+	status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+	mos7840_port->shadowLCR = Data;
+	dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data);
+	dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+	    mos7840_port->shadowLCR);
+
+	//Data = 0x03;
+	//status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data);
+	//mos7840_port->shadowLCR=Data;//Need to add later
+
+	Data |= SERIAL_LCR_DLAB;	//data latch enable in LCR 0x80
+	status = 0;
+	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+	//Data = 0x0c;
+	//status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data);
+	Data = 0x00;
+	status = 0;
+	status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);
+	dbg("mos7840_write:DLL value is %x\n", Data);
+
+	Data = 0x0;
+	status = 0;
+	status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);
+	dbg("mos7840_write:DLM value is %x\n", Data);
+
+	Data = Data & ~SERIAL_LCR_DLAB;
+	dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+	    mos7840_port->shadowLCR);
+	status = 0;
+	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+#endif
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Port Paranoia failed \n");
+		return -1;
+	}
+
+	serial = port->serial;
+	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+		dbg("%s", "Serial Paranoia failed \n");
+		return -1;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+	if (mos7840_port == NULL) {
+		dbg("%s", "mos7840_port is NULL\n");
+		return -1;
+	}
+
+	/* try to find a free urb in the list */
+	urb = NULL;
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+			urb = mos7840_port->write_urb_pool[i];
+			dbg("\nURB:%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);
+
+	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);
+	}
+
+	/* 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,
+			  mos7840_bulk_out_data_callback, mos7840_port);
+
+	data1 = urb->transfer_buffer;
+	dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress);
+
+	/* 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;
+	mos7840_port->icount.tx += transfer_size;
+	dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
+      exit:
+
+	return bytes_sent;
+
+}
+
+/*****************************************************************************
+ * mos7840_throttle
+ *	this function is called by the tty driver when it wants to stop the data
+ *	being read from the port.
+ *****************************************************************************/
+
+static void mos7840_throttle(struct usb_serial_port *port)
+{
+	struct moschip_port *mos7840_port;
+	struct tty_struct *tty;
+	int status;
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return;
+	}
+
+	dbg("- port %d\n", port->number);
+
+	mos7840_port = mos7840_get_port_private(port);
+
+	if (mos7840_port == NULL)
+		return;
+
+	if (!mos7840_port->open) {
+		dbg("%s\n", "port not opened");
+		return;
+	}
+
+	dbg("%s", "Entering .......... \n");
+
+	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 = mos7840_write(port, &stop_char, 1);
+		if (status <= 0) {
+			return;
+		}
+	}
+
+	/* if we are implementing RTS/CTS, toggle that line */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		mos7840_port->shadowMCR &= ~MCR_RTS;
+		status = 0;
+		status =
+		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+					 mos7840_port->shadowMCR);
+
+		if (status < 0) {
+			return;
+		}
+	}
+
+	return;
+}
+
+/*****************************************************************************
+ * mos7840_unthrottle
+ *	this function is called by the tty driver when it wants to resume the data
+ *	being read from the port (called after SerialThrottle is called)
+ *****************************************************************************/
+static void mos7840_unthrottle(struct usb_serial_port *port)
+{
+	struct tty_struct *tty;
+	int status;
+	struct moschip_port *mos7840_port = mos7840_get_port_private(port);
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return;
+	}
+
+	if (mos7840_port == NULL)
+		return;
+
+	if (!mos7840_port->open) {
+		dbg("%s - port not opened", __FUNCTION__);
+		return;
+	}
+
+	dbg("%s", "Entering .......... \n");
+
+	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 = mos7840_write(port, &start_char, 1);
+		if (status <= 0) {
+			return;
+		}
+	}
+
+	/* if we are implementing RTS/CTS, toggle that line */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		mos7840_port->shadowMCR |= MCR_RTS;
+		status = 0;
+		status =
+		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+					 mos7840_port->shadowMCR);
+		if (status < 0) {
+			return;
+		}
+	}
+
+	return;
+}
+
+static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+	struct moschip_port *mos7840_port;
+	unsigned int result;
+	__u16 msr;
+	__u16 mcr;
+	int status = 0;
+	mos7840_port = mos7840_get_port_private(port);
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (mos7840_port == NULL)
+		return -ENODEV;
+
+	status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
+	status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
+	result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
+	    | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
+	    | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)
+	    | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)
+	    | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)
+	    | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
+	    | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
+
+	dbg("%s - 0x%04X", __FUNCTION__, result);
+
+	return result;
+}
+
+static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+			    unsigned int set, unsigned int clear)
+{
+	struct moschip_port *mos7840_port;
+	unsigned int mcr;
+	unsigned int status;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	mos7840_port = mos7840_get_port_private(port);
+
+	if (mos7840_port == NULL)
+		return -ENODEV;
+
+	mcr = mos7840_port->shadowMCR;
+	if (clear & TIOCM_RTS)
+		mcr &= ~MCR_RTS;
+	if (clear & TIOCM_DTR)
+		mcr &= ~MCR_DTR;
+	if (clear & TIOCM_LOOP)
+		mcr &= ~MCR_LOOPBACK;
+
+	if (set & TIOCM_RTS)
+		mcr |= MCR_RTS;
+	if (set & TIOCM_DTR)
+		mcr |= MCR_DTR;
+	if (set & TIOCM_LOOP)
+		mcr |= MCR_LOOPBACK;
+
+	mos7840_port->shadowMCR = mcr;
+
+	status = 0;
+	status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
+	if (status < 0) {
+		dbg("setting MODEM_CONTROL_REGISTER Failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************
+ * mos7840_calc_baud_rate_divisor
+ *	this function calculates the proper baud rate divisor for the specified
+ *	baud rate.
+ *****************************************************************************/
+static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
+					  __u16 * clk_sel_val)
+{
+
+	dbg("%s - %d", __FUNCTION__, baudRate);
+
+	if (baudRate <= 115200) {
+		*divisor = 115200 / baudRate;
+		*clk_sel_val = 0x0;
+	}
+	if ((baudRate > 115200) && (baudRate <= 230400)) {
+		*divisor = 230400 / baudRate;
+		*clk_sel_val = 0x10;
+	} else if ((baudRate > 230400) && (baudRate <= 403200)) {
+		*divisor = 403200 / baudRate;
+		*clk_sel_val = 0x20;
+	} else if ((baudRate > 403200) && (baudRate <= 460800)) {
+		*divisor = 460800 / baudRate;
+		*clk_sel_val = 0x30;
+	} else if ((baudRate > 460800) && (baudRate <= 806400)) {
+		*divisor = 806400 / baudRate;
+		*clk_sel_val = 0x40;
+	} else if ((baudRate > 806400) && (baudRate <= 921600)) {
+		*divisor = 921600 / baudRate;
+		*clk_sel_val = 0x50;
+	} else if ((baudRate > 921600) && (baudRate <= 1572864)) {
+		*divisor = 1572864 / baudRate;
+		*clk_sel_val = 0x60;
+	} else if ((baudRate > 1572864) && (baudRate <= 3145728)) {
+		*divisor = 3145728 / baudRate;
+		*clk_sel_val = 0x70;
+	}
+	return 0;
+
+#ifdef NOTMCS7840
+
+	for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) {
+		if (mos7840_divisor_table[i].BaudRate == baudrate) {
+			*divisor = mos7840_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\n", baudrate, custom);
+		return 0;
+	}
+
+	dbg("%s\n", " Baud calculation Failed...");
+	return -1;
+#endif
+}
+
+/*****************************************************************************
+ * mos7840_send_cmd_write_baud_rate
+ *	this function sends the proper command to change the baud rate of the
+ *	specified port.
+ *****************************************************************************/
+
+static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+					    int baudRate)
+{
+	int divisor = 0;
+	int status;
+	__u16 Data;
+	unsigned char number;
+	__u16 clk_sel_val;
+	struct usb_serial_port *port;
+
+	if (mos7840_port == NULL)
+		return -1;
+
+	port = (struct usb_serial_port *)mos7840_port->port;
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return -1;
+	}
+
+	if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+		dbg("%s", "Invalid Serial \n");
+		return -1;
+	}
+
+	dbg("%s", "Entering .......... \n");
+
+	number = mos7840_port->port->number - mos7840_port->port->serial->minor;
+
+	dbg("%s - port = %d, baud = %d", __FUNCTION__,
+	    mos7840_port->port->number, baudRate);
+	//reset clk_uart_sel in spregOffset
+	if (baudRate > 115200) {
+#ifdef HW_flow_control
+		//NOTE: need to see the pther register to modify
+		//setting h/w flow control bit to 1;
+		status = 0;
+		Data = 0x2b;
+		mos7840_port->shadowMCR = Data;
+		status =
+		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+		if (status < 0) {
+			dbg("Writing spreg failed in set_serial_baud\n");
+			return -1;
+		}
+#endif
+
+	} else {
+#ifdef HW_flow_control
+		//setting h/w flow control bit to 0;
+		status = 0;
+		Data = 0xb;
+		mos7840_port->shadowMCR = Data;
+		status =
+		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+		if (status < 0) {
+			dbg("Writing spreg failed in set_serial_baud\n");
+			return -1;
+		}
+#endif
+
+	}
+
+	if (1)			//baudRate <= 115200)
+	{
+		clk_sel_val = 0x0;
+		Data = 0x0;
+		status = 0;
+		status =
+		    mos7840_calc_baud_rate_divisor(baudRate, &divisor,
+						   &clk_sel_val);
+		status =
+		    mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
+					 &Data);
+		if (status < 0) {
+			dbg("reading spreg failed in set_serial_baud\n");
+			return -1;
+		}
+		Data = (Data & 0x8f) | clk_sel_val;
+		status = 0;
+		status =
+		    mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+		if (status < 0) {
+			dbg("Writing spreg failed in set_serial_baud\n");
+			return -1;
+		}
+		/* Calculate the Divisor */
+
+		if (status) {
+			err("%s - bad baud rate", __FUNCTION__);
+			dbg("%s\n", "bad baud rate");
+			return status;
+		}
+		/* Enable access to divisor latch */
+		Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB;
+		mos7840_port->shadowLCR = Data;
+		mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+		/* Write the divisor */
+		Data = (unsigned char)(divisor & 0xff);
+		dbg("set_serial_baud Value to write DLL is %x\n", Data);
+		mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
+
+		Data = (unsigned char)((divisor & 0xff00) >> 8);
+		dbg("set_serial_baud Value to write DLM is %x\n", Data);
+		mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
+
+		/* Disable access to divisor latch */
+		Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB;
+		mos7840_port->shadowLCR = Data;
+		mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+	}
+
+	return status;
+}
+
+/*****************************************************************************
+ * mos7840_change_port_settings
+ *	This routine is called to set the UART on the device to match
+ *      the specified new settings.
+ *****************************************************************************/
+
+static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+					 struct termios *old_termios)
+{
+	struct tty_struct *tty;
+	int baud;
+	unsigned cflag;
+	unsigned iflag;
+	__u8 lData;
+	__u8 lParity;
+	__u8 lStop;
+	int status;
+	__u16 Data;
+	struct usb_serial_port *port;
+	struct usb_serial *serial;
+
+	if (mos7840_port == NULL)
+		return;
+
+	port = (struct usb_serial_port *)mos7840_port->port;
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return;
+	}
+
+	if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+		dbg("%s", "Invalid Serial \n");
+		return;
+	}
+
+	serial = port->serial;
+
+	dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
+
+	if (!mos7840_port->open) {
+		dbg("%s - port not opened", __FUNCTION__);
+		return;
+	}
+
+	tty = mos7840_port->port->tty;
+
+	if ((!tty) || (!tty->termios)) {
+		dbg("%s - no tty structures", __FUNCTION__);
+		return;
+	}
+
+	dbg("%s", "Entering .......... \n");
+
+	lData = LCR_BITS_8;
+	lStop = LCR_STOP_1;
+	lParity = LCR_PAR_NONE;
+
+	cflag = tty->termios->c_cflag;
+	iflag = tty->termios->c_iflag;
+
+	/* Change the number of bits */
+	if (cflag & CSIZE) {
+		switch (cflag & CSIZE) {
+		case CS5:
+			lData = LCR_BITS_5;
+			break;
+
+		case CS6:
+			lData = LCR_BITS_6;
+			break;
+
+		case CS7:
+			lData = LCR_BITS_7;
+			break;
+		default:
+		case CS8:
+			lData = LCR_BITS_8;
+			break;
+		}
+	}
+	/* Change the Parity bit */
+	if (cflag & PARENB) {
+		if (cflag & PARODD) {
+			lParity = LCR_PAR_ODD;
+			dbg("%s - parity = odd", __FUNCTION__);
+		} else {
+			lParity = LCR_PAR_EVEN;
+			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 = LCR_STOP_2;
+		dbg("%s - stop bits = 2", __FUNCTION__);
+	} else {
+		lStop = LCR_STOP_1;
+		dbg("%s - stop bits = 1", __FUNCTION__);
+	}
+
+	/* Update the LCR with the correct value */
+	mos7840_port->shadowLCR &=
+	    ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+	mos7840_port->shadowLCR |= (lData | lParity | lStop);
+
+	dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n",
+	    mos7840_port->shadowLCR);
+	/* Disable Interrupts */
+	Data = 0x00;
+	mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+	Data = 0x00;
+	mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+
+	Data = 0xcf;
+	mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+
+	/* Send the updated LCR value to the mos7840 */
+	Data = mos7840_port->shadowLCR;
+
+	mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+	Data = 0x00b;
+	mos7840_port->shadowMCR = Data;
+	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+	Data = 0x00b;
+	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+	/* set up the MCR register and send it to the mos7840 */
+
+	mos7840_port->shadowMCR = MCR_MASTER_IE;
+	if (cflag & CBAUD) {
+		mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);
+	}
+
+	if (cflag & CRTSCTS) {
+		mos7840_port->shadowMCR |= (MCR_XON_ANY);
+
+	} else {
+		mos7840_port->shadowMCR &= ~(MCR_XON_ANY);
+	}
+
+	Data = mos7840_port->shadowMCR;
+	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(tty);
+
+	if (!baud) {
+		/* pick a default, any default... */
+		dbg("%s\n", "Picked default baud...");
+		baud = 9600;
+	}
+
+	dbg("%s - baud rate = %d", __FUNCTION__, baud);
+	status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
+
+	/* Enable Interrupts */
+	Data = 0x0c;
+	mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+	if (mos7840_port->read_urb->status != -EINPROGRESS) {
+		mos7840_port->read_urb->dev = serial->dev;
+
+		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+
+		if (status) {
+			dbg(" usb_submit_urb(read bulk) failed, status = %d",
+			    status);
+		}
+	}
+	wake_up(&mos7840_port->delta_msr_wait);
+	mos7840_port->delta_msr_cond = 1;
+	dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n",
+	    mos7840_port->shadowLCR);
+
+	return;
+}
+
+/*****************************************************************************
+ * mos7840_set_termios
+ *	this function is called by the tty driver when it wants to change
+ *	the termios structure
+ *****************************************************************************/
+
+static void mos7840_set_termios(struct usb_serial_port *port,
+				struct termios *old_termios)
+{
+	int status;
+	unsigned int cflag;
+	struct usb_serial *serial;
+	struct moschip_port *mos7840_port;
+	struct tty_struct *tty;
+	dbg("mos7840_set_termios: START\n");
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return;
+	}
+
+	serial = port->serial;
+
+	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+		dbg("%s", "Invalid Serial \n");
+		return;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+
+	if (mos7840_port == NULL)
+		return;
+
+	tty = port->tty;
+
+	if (!port->tty || !port->tty->termios) {
+		dbg("%s - no tty or termios", __FUNCTION__);
+		return;
+	}
+
+	if (!mos7840_port->open) {
+		dbg("%s - port not opened", __FUNCTION__);
+		return;
+	}
+
+	dbg("%s\n", "setting termios - ");
+
+	cflag = tty->termios->c_cflag;
+
+	if (!cflag) {
+		dbg("%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("%s\n", "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 */
+
+	mos7840_change_port_settings(mos7840_port, old_termios);
+
+	if (!mos7840_port->read_urb) {
+		dbg("%s", "URB KILLED !!!!!\n");
+		return;
+	}
+
+	if (mos7840_port->read_urb->status != -EINPROGRESS) {
+		mos7840_port->read_urb->dev = serial->dev;
+		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+		if (status) {
+			dbg(" usb_submit_urb(read bulk) failed, status = %d",
+			    status);
+		}
+	}
+	return;
+}
+
+/*****************************************************************************
+ * mos7840_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 mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+				unsigned int *value)
+{
+	int count;
+	unsigned int result = 0;
+
+	count = mos7840_chars_in_buffer(mos7840_port->port);
+	if (count == 0) {
+		dbg("%s -- Empty", __FUNCTION__);
+		result = TIOCSER_TEMT;
+	}
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_bytes_avail - get number of bytes available
+ *
+ * Purpose: Let user call ioctl to get the count of number of bytes available.
+ *****************************************************************************/
+
+static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
+				   unsigned int *value)
+{
+	unsigned int result = 0;
+	struct tty_struct *tty = mos7840_port->port->tty;
+
+	if (!tty)
+		return -ENOIOCTLCMD;
+
+	result = tty->read_cnt;
+
+	dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result);
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+
+	return -ENOIOCTLCMD;
+}
+
+/*****************************************************************************
+ * mos7840_set_modem_info
+ *      function to set modem info
+ *****************************************************************************/
+
+static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
+				  unsigned int cmd, unsigned int *value)
+{
+	unsigned int mcr;
+	unsigned int arg;
+	__u16 Data;
+	int status;
+	struct usb_serial_port *port;
+
+	if (mos7840_port == NULL)
+		return -1;
+
+	port = (struct usb_serial_port *)mos7840_port->port;
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return -1;
+	}
+
+	mcr = mos7840_port->shadowMCR;
+
+	if (copy_from_user(&arg, value, sizeof(int)))
+		return -EFAULT;
+
+	switch (cmd) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS)
+			mcr |= MCR_RTS;
+		if (arg & TIOCM_DTR)
+			mcr |= MCR_RTS;
+		if (arg & TIOCM_LOOP)
+			mcr |= MCR_LOOPBACK;
+		break;
+
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			mcr &= ~MCR_RTS;
+		if (arg & TIOCM_DTR)
+			mcr &= ~MCR_RTS;
+		if (arg & TIOCM_LOOP)
+			mcr &= ~MCR_LOOPBACK;
+		break;
+
+	case TIOCMSET:
+		/* turn off the RTS and DTR and LOOPBACK
+		 * and then only turn on what was asked to */
+		mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
+		mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
+		mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+		mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
+		break;
+	}
+
+	mos7840_port->shadowMCR = mcr;
+
+	Data = mos7840_port->shadowMCR;
+	status = 0;
+	status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+	if (status < 0) {
+		dbg("setting MODEM_CONTROL_REGISTER Failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_modem_info
+ *      function to get modem info
+ *****************************************************************************/
+
+static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
+				  unsigned int *value)
+{
+	unsigned int result = 0;
+	__u16 msr;
+	unsigned int mcr = mos7840_port->shadowMCR;
+	int status = 0;
+	status =
+	    mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER,
+				 &msr);
+	result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)	/* 0x002 */
+	    |((mcr & MCR_RTS) ? TIOCM_RTS : 0)	/* 0x004 */
+	    |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)	/* 0x020 */
+	    |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)	/* 0x040 */
+	    |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)	/* 0x080 */
+	    |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);	/* 0x100 */
+
+	dbg("%s -- %x", __FUNCTION__, result);
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_serial_info
+ *      function to get information about serial port
+ *****************************************************************************/
+
+static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
+				   struct serial_struct *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (mos7840_port == NULL)
+		return -1;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	tmp.type = PORT_16550A;
+	tmp.line = mos7840_port->port->serial->minor;
+	tmp.port = mos7840_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;
+}
+
+/*****************************************************************************
+ * SerialIoctl
+ *	this function handles any ioctl calls to the driver
+ *****************************************************************************/
+
+static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	struct moschip_port *mos7840_port;
+	struct tty_struct *tty;
+
+	struct async_icount cnow;
+	struct async_icount cprev;
+	struct serial_icounter_struct icount;
+	int mosret = 0;
+	int retval;
+	struct tty_ldisc *ld;
+
+	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+		dbg("%s", "Invalid port \n");
+		return -1;
+	}
+
+	mos7840_port = mos7840_get_port_private(port);
+	tty = mos7840_port->port->tty;
+
+	if (mos7840_port == NULL)
+		return -1;
+
+	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+
+	switch (cmd) {
+		/* return number of bytes available */
+
+	case TIOCINQ:
+		dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
+		return mos7840_get_bytes_avail(mos7840_port,
+					       (unsigned int *)arg);
+		break;
+
+	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);
+		if (retval)
+			return retval;
+
+		ld = tty_ldisc_ref(tty);
+		switch (arg) {
+		case TCIFLUSH:
+			if (ld && ld->flush_buffer)
+				ld->flush_buffer(tty);
+			break;
+		case TCIOFLUSH:
+			if (ld && ld->flush_buffer)
+				ld->flush_buffer(tty);
+			/* fall through */
+		case TCOFLUSH:
+			if (tty->driver->flush_buffer)
+				tty->driver->flush_buffer(tty);
+			break;
+		default:
+			tty_ldisc_deref(ld);
+			return -EINVAL;
+		}
+		tty_ldisc_deref(ld);
+		return 0;
+
+	case TCGETS:
+		if (kernel_termios_to_user_termios
+		    ((struct termios __user *)arg, 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 0;
+
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
+		    port->number);
+		mosret =
+		    mos7840_set_modem_info(mos7840_port, cmd,
+					   (unsigned int *)arg);
+		return mosret;
+
+	case TIOCMGET:
+		dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
+		return mos7840_get_modem_info(mos7840_port,
+					      (unsigned int *)arg);
+
+	case TIOCGSERIAL:
+		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
+		return mos7840_get_serial_info(mos7840_port,
+					       (struct serial_struct *)arg);
+
+	case TIOCSSERIAL:
+		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
+		break;
+
+	case TIOCMIWAIT:
+		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+		cprev = mos7840_port->icount;
+		while (1) {
+			//interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+			mos7840_port->delta_msr_cond = 0;
+			wait_event_interruptible(mos7840_port->delta_msr_wait,
+						 (mos7840_port->
+						  delta_msr_cond == 1));
+
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			cnow = mos7840_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 = mos7840_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 *)arg, &icount, sizeof(icount)))
+			return -EFAULT;
+		return 0;
+
+	case TIOCEXBAUD:
+		return 0;
+	default:
+		break;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static int mos7840_calc_num_ports(struct usb_serial *serial)
+{
+
+	dbg("numberofendpoints: %d \n",
+	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
+	dbg("numberofendpoints: %d \n",
+	    (int)serial->interface->altsetting->desc.bNumEndpoints);
+	if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
+		mos7840_num_ports = 2;
+		serial->type->num_ports = 2;
+	} else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+		mos7840_num_ports = 4;
+		serial->type->num_bulk_in = 4;
+		serial->type->num_bulk_out = 4;
+		serial->type->num_ports = 4;
+	}
+
+	return mos7840_num_ports;
+}
+
+/****************************************************************************
+ * mos7840_startup
+ ****************************************************************************/
+
+static int mos7840_startup(struct usb_serial *serial)
+{
+	struct moschip_port *mos7840_port;
+	struct usb_device *dev;
+	int i, status;
+
+	__u16 Data;
+	dbg("%s \n", " mos7840_startup :entering..........");
+
+	if (!serial) {
+		dbg("%s\n", "Invalid Handler");
+		return -1;
+	}
+
+	dev = serial->dev;
+
+	dbg("%s\n", "Entering...");
+
+	/* we set up the pointers to the endpoints in the mos7840_open *
+	 * function, as the structures aren't created yet.             */
+
+	/* set up port private structures */
+	for (i = 0; i < serial->num_ports; ++i) {
+		mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL);
+		if (mos7840_port == NULL) {
+			err("%s - Out of memory", __FUNCTION__);
+			return -ENOMEM;
+		}
+		memset(mos7840_port, 0, sizeof(struct moschip_port));
+
+		/* Initialize all port interrupt end point to port 0 int endpoint *
+		 * Our device has only one interrupt end point comman to all port */
+
+		mos7840_port->port = serial->port[i];
+		mos7840_set_port_private(serial->port[i], mos7840_port);
+
+		mos7840_port->port_num = ((serial->port[i]->number -
+					   (serial->port[i]->serial->minor)) +
+					  1);
+
+		if (mos7840_port->port_num == 1) {
+			mos7840_port->SpRegOffset = 0x0;
+			mos7840_port->ControlRegOffset = 0x1;
+			mos7840_port->DcrRegOffset = 0x4;
+		} else if ((mos7840_port->port_num == 2)
+			   && (mos7840_num_ports == 4)) {
+			mos7840_port->SpRegOffset = 0x8;
+			mos7840_port->ControlRegOffset = 0x9;
+			mos7840_port->DcrRegOffset = 0x16;
+		} else if ((mos7840_port->port_num == 2)
+			   && (mos7840_num_ports == 2)) {
+			mos7840_port->SpRegOffset = 0xa;
+			mos7840_port->ControlRegOffset = 0xb;
+			mos7840_port->DcrRegOffset = 0x19;
+		} else if ((mos7840_port->port_num == 3)
+			   && (mos7840_num_ports == 4)) {
+			mos7840_port->SpRegOffset = 0xa;
+			mos7840_port->ControlRegOffset = 0xb;
+			mos7840_port->DcrRegOffset = 0x19;
+		} else if ((mos7840_port->port_num == 4)
+			   && (mos7840_num_ports == 4)) {
+			mos7840_port->SpRegOffset = 0xc;
+			mos7840_port->ControlRegOffset = 0xd;
+			mos7840_port->DcrRegOffset = 0x1c;
+		}
+		mos7840_dump_serial_port(mos7840_port);
+
+		mos7840_set_port_private(serial->port[i], mos7840_port);
+
+		//enable rx_disable bit in control register
+
+		status =
+		    mos7840_get_reg_sync(serial->port[i],
+					 mos7840_port->ControlRegOffset, &Data);
+		if (status < 0) {
+			dbg("Reading ControlReg failed status-0x%x\n", status);
+			break;
+		} else
+			dbg("ControlReg Reading success val is %x, status%d\n",
+			    Data, status);
+		Data |= 0x08;	//setting driver done bit
+		Data |= 0x04;	//sp1_bit to have cts change reflect in modem status reg
+
+		//Data |= 0x20; //rx_disable bit
+		status = 0;
+		status =
+		    mos7840_set_reg_sync(serial->port[i],
+					 mos7840_port->ControlRegOffset, Data);
+		if (status < 0) {
+			dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+			break;
+		} else
+			dbg("ControlReg Writing success(rx_disable) status%d\n",
+			    status);
+
+		//Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3
+		Data = 0x01;
+		status = 0;
+		status =
+		    mos7840_set_reg_sync(serial->port[i],
+					 (__u16) (mos7840_port->DcrRegOffset +
+						  0), Data);
+		if (status < 0) {
+			dbg("Writing DCR0 failed status-0x%x\n", status);
+			break;
+		} else
+			dbg("DCR0 Writing success status%d\n", status);
+
+		Data = 0x05;
+		status = 0;
+		status =
+		    mos7840_set_reg_sync(serial->port[i],
+					 (__u16) (mos7840_port->DcrRegOffset +
+						  1), Data);
+		if (status < 0) {
+			dbg("Writing DCR1 failed status-0x%x\n", status);
+			break;
+		} else
+			dbg("DCR1 Writing success status%d\n", status);
+
+		Data = 0x24;
+		status = 0;
+		status =
+		    mos7840_set_reg_sync(serial->port[i],
+					 (__u16) (mos7840_port->DcrRegOffset +
+						  2), Data);
+		if (status < 0) {
+			dbg("Writing DCR2 failed status-0x%x\n", status);
+			break;
+		} else
+			dbg("DCR2 Writing success status%d\n", status);
+
+		// write values in clkstart0x0 and clkmulti 0x20
+		Data = 0x0;
+		status = 0;
+		status =
+		    mos7840_set_reg_sync(serial->port[i],
+					 CLK_START_VALUE_REGISTER, Data);
+		if (status < 0) {
+			dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+			break;
+		} else
+			dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
+
+		Data = 0x20;
+		status = 0;
+		status =
+		    mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
+					 Data);
+		if (status < 0) {
+			dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
+			    status);
+			break;
+		} else
+			dbg("CLK_MULTI_REGISTER Writing success status%d\n",
+			    status);
+
+		//write value 0x0 to scratchpad register
+		Data = 0x00;
+		status = 0;
+		status =
+		    mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
+					 Data);
+		if (status < 0) {
+			dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n",
+			    status);
+			break;
+		} else
+			dbg("SCRATCH_PAD_REGISTER Writing success status%d\n",
+			    status);
+
+		//Zero Length flag register
+		if ((mos7840_port->port_num != 1)
+		    && (mos7840_num_ports == 2)) {
+
+			Data = 0xff;
+			status = 0;
+			status = mos7840_set_reg_sync(serial->port[i],
+						      (__u16) (ZLP_REG1 +
+							       ((__u16)
+								mos7840_port->
+								port_num)),
+						      Data);
+			dbg("ZLIP offset%x\n",
+			    (__u16) (ZLP_REG1 +
+				     ((__u16) mos7840_port->port_num)));
+			if (status < 0) {
+				dbg("Writing ZLP_REG%d failed status-0x%x\n",
+				    i + 2, status);
+				break;
+			} else
+				dbg("ZLP_REG%d Writing success status%d\n",
+				    i + 2, status);
+		} else {
+			Data = 0xff;
+			status = 0;
+			status = mos7840_set_reg_sync(serial->port[i],
+						      (__u16) (ZLP_REG1 +
+							       ((__u16)
+								mos7840_port->
+								port_num) -
+							       0x1), Data);
+			dbg("ZLIP offset%x\n",
+			    (__u16) (ZLP_REG1 +
+				     ((__u16) mos7840_port->port_num) - 0x1));
+			if (status < 0) {
+				dbg("Writing ZLP_REG%d failed status-0x%x\n",
+				    i + 1, status);
+				break;
+			} else
+				dbg("ZLP_REG%d Writing success status%d\n",
+				    i + 1, status);
+
+		}
+		mos7840_port->control_urb = usb_alloc_urb(0, SLAB_ATOMIC);
+		mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+
+	}
+
+	//Zero Length flag enable
+	Data = 0x0f;
+	status = 0;
+	status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+	if (status < 0) {
+		dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
+		return -1;
+	} else
+		dbg("ZLP_REG5 Writing success status%d\n", status);
+
+	/* setting configuration feature to one */
+	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			(__u8) 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 5 * HZ);
+	return 0;
+}
+
+/****************************************************************************
+ * mos7840_shutdown
+ *	This function is called whenever the device is removed from the usb bus.
+ ****************************************************************************/
+
+static void mos7840_shutdown(struct usb_serial *serial)
+{
+	int i;
+	struct moschip_port *mos7840_port;
+	dbg("%s \n", " shutdown :entering..........");
+
+	if (!serial) {
+		dbg("%s", "Invalid Handler \n");
+		return;
+	}
+
+	/*      check for the ports to be closed,close the ports and disconnect         */
+
+	/* free private structure allocated for serial port  *
+	 * stop reads and writes on all ports                */
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		mos7840_port = mos7840_get_port_private(serial->port[i]);
+		kfree(mos7840_port->ctrl_buf);
+		usb_kill_urb(mos7840_port->control_urb);
+		kfree(mos7840_port);
+		mos7840_set_port_private(serial->port[i], NULL);
+	}
+
+	dbg("%s\n", "Thank u :: ");
+
+}
+
+static struct usb_serial_driver moschip7840_4port_device = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = "mos7840",
+		   },
+	.description = DRIVER_DESC,
+	.id_table = moschip_port_id_table,
+	.num_interrupt_in = 1,	//NUM_DONT_CARE,//1,
+#ifdef check
+	.num_bulk_in = 4,
+	.num_bulk_out = 4,
+	.num_ports = 4,
+#endif
+	.open = mos7840_open,
+	.close = mos7840_close,
+	.write = mos7840_write,
+	.write_room = mos7840_write_room,
+	.chars_in_buffer = mos7840_chars_in_buffer,
+	.throttle = mos7840_throttle,
+	.unthrottle = mos7840_unthrottle,
+	.calc_num_ports = mos7840_calc_num_ports,
+#ifdef MCSSerialProbe
+	.probe = mos7840_serial_probe,
+#endif
+	.ioctl = mos7840_ioctl,
+	.set_termios = mos7840_set_termios,
+	.break_ctl = mos7840_break,
+	.tiocmget = mos7840_tiocmget,
+	.tiocmset = mos7840_tiocmset,
+	.attach = mos7840_startup,
+	.shutdown = mos7840_shutdown,
+	.read_bulk_callback = mos7840_bulk_in_callback,
+	.read_int_callback = mos7840_interrupt_callback,
+};
+
+static struct usb_driver io_driver = {
+	.name = "mos7840",
+	.probe = usb_serial_probe,
+	.disconnect = usb_serial_disconnect,
+	.id_table = moschip_id_table_combined,
+};
+
+/****************************************************************************
+ * moschip7840_init
+ *	This is called by the module subsystem, or on startup to initialize us
+ ****************************************************************************/
+static int __init moschip7840_init(void)
+{
+	int retval;
+
+	dbg("%s \n", " mos7840_init :entering..........");
+
+	/* Register with the usb serial */
+	retval = usb_serial_register(&moschip7840_4port_device);
+
+	if (retval)
+		goto failed_port_device_register;
+
+	dbg("%s\n", "Entring...");
+	info(DRIVER_DESC " " DRIVER_VERSION);
+
+	/* Register with the usb */
+	retval = usb_register(&io_driver);
+
+	if (retval)
+		goto failed_usb_register;
+
+	if (retval == 0) {
+		dbg("%s\n", "Leaving...");
+		return 0;
+	}
+
+      failed_usb_register:
+	usb_serial_deregister(&moschip7840_4port_device);
+
+      failed_port_device_register:
+
+	return retval;
+}
+
+/****************************************************************************
+ * moschip7840_exit
+ *	Called when the driver is about to be unloaded.
+ ****************************************************************************/
+static void __exit moschip7840_exit(void)
+{
+
+	dbg("%s \n", " mos7840_exit :entering..........");
+
+	usb_deregister(&io_driver);
+
+	usb_serial_deregister(&moschip7840_4port_device);
+
+	dbg("%s\n", "Entring...");
+}
+
+module_init(moschip7840_init);
+module_exit(moschip7840_exit);
+
+/* Module information */
+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/omninet.c b/drivers/usb/serial/omninet.c
index e49f409..a764ff4e 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -256,14 +256,14 @@
 		return (0);
 	}
 
-	spin_lock(&wport->lock);
+	spin_lock_bh(&wport->lock);
 	if (wport->write_urb_busy) {
-		spin_unlock(&wport->lock);
+		spin_unlock_bh(&wport->lock);
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
 	}
 	wport->write_urb_busy = 1;
-	spin_unlock(&wport->lock);
+	spin_unlock_bh(&wport->lock);
 
 	count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 65e4d04..9c18173 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -81,10 +81,12 @@
 	{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
 	{ USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
 	{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
+	{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
+	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver pl2303_driver = {
 	.name =		"pl2303",
@@ -127,65 +129,6 @@
 #define UART_OVERRUN_ERROR		0x40
 #define UART_CTS			0x80
 
-/* function prototypes for a PL2303 serial converter */
-static int pl2303_open (struct usb_serial_port *port, struct file *filp);
-static void pl2303_close (struct usb_serial_port *port, struct file *filp);
-static void pl2303_set_termios (struct usb_serial_port *port,
-				struct termios *old);
-static int pl2303_ioctl (struct usb_serial_port *port, struct file *file,
-			 unsigned int cmd, unsigned long arg);
-static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs);
-static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static int pl2303_write (struct usb_serial_port *port,
-			 const unsigned char *buf, int count);
-static void pl2303_send (struct usb_serial_port *port);
-static int pl2303_write_room(struct usb_serial_port *port);
-static int pl2303_chars_in_buffer(struct usb_serial_port *port);
-static void pl2303_break_ctl(struct usb_serial_port *port,int break_state);
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-			    unsigned int set, unsigned int clear);
-static int pl2303_startup (struct usb_serial *serial);
-static void pl2303_shutdown (struct usb_serial *serial);
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
-static void pl2303_buf_free(struct pl2303_buf *pb);
-static void pl2303_buf_clear(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
-	unsigned int count);
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
-	unsigned int count);
-
-
-/* All of the device info needed for the PL2303 SIO serial converter */
-static struct usb_serial_driver pl2303_device = {
-	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"pl2303",
-	},
-	.id_table =		id_table,
-	.num_interrupt_in =	NUM_DONT_CARE,
-	.num_bulk_in =		1,
-	.num_bulk_out =		1,
-	.num_ports =		1,
-	.open =			pl2303_open,
-	.close =		pl2303_close,
-	.write =		pl2303_write,
-	.ioctl =		pl2303_ioctl,
-	.break_ctl =		pl2303_break_ctl,
-	.set_termios =		pl2303_set_termios,
-	.tiocmget =		pl2303_tiocmget,
-	.tiocmset =		pl2303_tiocmset,
-	.read_bulk_callback =	pl2303_read_bulk_callback,
-	.read_int_callback =	pl2303_read_int_callback,
-	.write_bulk_callback =	pl2303_write_bulk_callback,
-	.write_room =		pl2303_write_room,
-	.chars_in_buffer =	pl2303_chars_in_buffer,
-	.attach =		pl2303_startup,
-	.shutdown =		pl2303_shutdown,
-};
 
 enum pl2303_type {
 	type_0,		/* don't know the difference between type 0 and */
@@ -204,8 +147,166 @@
 	enum pl2303_type type;
 };
 
+/*
+ * pl2303_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+{
+	struct pl2303_buf *pb;
 
-static int pl2303_startup (struct usb_serial *serial)
+	if (size == 0)
+		return NULL;
+
+	pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+	if (pb == NULL)
+		return NULL;
+
+	pb->buf_buf = kmalloc(size, GFP_KERNEL);
+	if (pb->buf_buf == NULL) {
+		kfree(pb);
+		return NULL;
+	}
+
+	pb->buf_size = size;
+	pb->buf_get = pb->buf_put = pb->buf_buf;
+
+	return pb;
+}
+
+/*
+ * pl2303_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void pl2303_buf_free(struct pl2303_buf *pb)
+{
+	if (pb) {
+		kfree(pb->buf_buf);
+		kfree(pb);
+	}
+}
+
+/*
+ * pl2303_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void pl2303_buf_clear(struct pl2303_buf *pb)
+{
+	if (pb != NULL)
+		pb->buf_get = pb->buf_put;
+		/* equivalent to a get of all data available */
+}
+
+/*
+ * pl2303_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+{
+	if (pb == NULL)
+		return 0;
+
+	return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+{
+	if (pb == NULL)
+		return 0;
+
+	return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+				   unsigned int count)
+{
+	unsigned int len;
+
+	if (pb == NULL)
+		return 0;
+
+	len  = pl2303_buf_space_avail(pb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = pb->buf_buf + pb->buf_size - pb->buf_put;
+	if (count > len) {
+		memcpy(pb->buf_put, buf, len);
+		memcpy(pb->buf_buf, buf+len, count - len);
+		pb->buf_put = pb->buf_buf + count - len;
+	} else {
+		memcpy(pb->buf_put, buf, count);
+		if (count < len)
+			pb->buf_put += count;
+		else /* count == len */
+			pb->buf_put = pb->buf_buf;
+	}
+
+	return count;
+}
+
+/*
+ * pl2303_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+				   unsigned int count)
+{
+	unsigned int len;
+
+	if (pb == NULL)
+		return 0;
+
+	len = pl2303_buf_data_avail(pb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = pb->buf_buf + pb->buf_size - pb->buf_get;
+	if (count > len) {
+		memcpy(buf, pb->buf_get, len);
+		memcpy(buf+len, pb->buf_buf, count - len);
+		pb->buf_get = pb->buf_buf + count - len;
+	} else {
+		memcpy(buf, pb->buf_get, count);
+		if (count < len)
+			pb->buf_get += count;
+		else /* count == len */
+			pb->buf_get = pb->buf_buf;
+	}
+
+	return count;
+}
+
+static int pl2303_startup(struct usb_serial *serial)
 {
 	struct pl2303_private *priv;
 	enum pl2303_type type = type_0;
@@ -247,36 +348,17 @@
 	return -ENOMEM;
 }
 
-static int set_control_lines (struct usb_device *dev, u8 value)
+static int set_control_lines(struct usb_device *dev, u8 value)
 {
 	int retval;
 	
-	retval = usb_control_msg (dev, usb_sndctrlpipe (dev, 0),
-				  SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
-				  value, 0, NULL, 0, 100);
+	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
+				 value, 0, NULL, 0, 100);
 	dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
 	return retval;
 }
 
-static int pl2303_write (struct usb_serial_port *port,  const unsigned char *buf, int count)
-{
-	struct pl2303_private *priv = usb_get_serial_port_data(port);
-	unsigned long flags;
-
-	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
-
-	if (!count)
-		return count;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	count = pl2303_buf_put(priv->buf, buf, count);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	pl2303_send(port);
-
-	return count;
-}
-
 static void pl2303_send(struct usb_serial_port *port)
 {
 	int count, result;
@@ -293,7 +375,7 @@
 	}
 
 	count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer,
-		port->bulk_out_size);
+			       port->bulk_out_size);
 
 	if (count == 0) {
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -304,13 +386,15 @@
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
+			      port->write_urb->transfer_buffer);
 
 	port->write_urb->transfer_buffer_length = count;
 	port->write_urb->dev = port->serial->dev;
-	result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+		dev_err(&port->dev, "%s - failed submitting write urb,"
+			" error %d\n", __FUNCTION__, result);
 		priv->write_urb_in_use = 0;
 		// TODO: reschedule pl2303_send
 	}
@@ -318,6 +402,26 @@
 	usb_serial_port_softint(port);
 }
 
+static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
+			int count)
+{
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+
+	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+
+	if (!count)
+		return count;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	count = pl2303_buf_put(priv->buf, buf, count);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	pl2303_send(port);
+
+	return count;
+}
+
 static int pl2303_write_room(struct usb_serial_port *port)
 {
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -350,7 +454,8 @@
 	return chars;
 }
 
-static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void pl2303_set_termios(struct usb_serial_port *port,
+			       struct termios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -371,7 +476,8 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	if (!priv->termios_initialized) {
 		*(port->tty->termios) = tty_std_termios;
-		port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+		port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
+					      HUPCL | CLOCAL;
 		priv->termios_initialized = 1;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -380,24 +486,24 @@
 	/* check that they really want us to change something */
 	if (old_termios) {
 		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-		    dbg("%s - nothing to change...", __FUNCTION__);
-		    return;
+		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
+		     RELEVANT_IFLAG(old_termios->c_iflag))) {
+			dbg("%s - nothing to change...", __FUNCTION__);
+			return;
 		}
 	}
 
-	buf = kzalloc (7, GFP_KERNEL);
+	buf = kzalloc(7, GFP_KERNEL);
 	if (!buf) {
 		dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
 		return;
 	}
-	
-	i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
-			     GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
-			     0, 0, buf, 7, 100);
-	dbg ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
-	     buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
+	i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			    GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+			    0, 0, buf, 7, 100);
+	dbg("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
+	    buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
 	if (cflag & CSIZE) {
 		switch (cflag & CSIZE) {
@@ -429,7 +535,8 @@
 		case B230400:	baud = 230400;	break;
 		case B460800:	baud = 460800;	break;
 		default:
-			dev_err(&port->dev, "pl2303 driver does not support the baudrate requested (fix it)\n");
+			dev_err(&port->dev, "pl2303 driver does not support"
+				" the baudrate requested (fix it)\n");
 			break;
 	}
 	dbg("%s - baud = %d", __FUNCTION__, baud);
@@ -469,10 +576,10 @@
 		dbg("%s - parity = none", __FUNCTION__);
 	}
 
-	i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-			     SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 
-			     0, 0, buf, 7, 100);
-	dbg ("0x21:0x20:0:0  %d", i);
+	i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
+			    0, 0, buf, 7, 100);
+	dbg("0x21:0x20:0:0  %d", i);
 
 	/* change control lines if we are switching to or from B0 */
 	spin_lock_irqsave(&priv->lock, flags);
@@ -488,13 +595,13 @@
 	} else {
 		spin_unlock_irqrestore(&priv->lock, flags);
 	}
-	
+
 	buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
 
-	i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
-			     GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
-			     0, 0, buf, 7, 100);
-	dbg ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
+	i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			    GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+			    0, 0, buf, 7, 100);
+	dbg("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
 	     buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
 	if (cflag & CRTSCTS) {
@@ -503,18 +610,82 @@
 			index = 0x61;
 		else
 			index = 0x41;
-		i = usb_control_msg(serial->dev, 
+		i = usb_control_msg(serial->dev,
 				    usb_sndctrlpipe(serial->dev, 0),
 				    VENDOR_WRITE_REQUEST,
 				    VENDOR_WRITE_REQUEST_TYPE,
 				    0x0, index, NULL, 0, 100);
-		dbg ("0x40:0x1:0x0:0x%x  %d", index, i);
+		dbg("0x40:0x1:0x0:0x%x  %d", index, i);
 	}
 
-	kfree (buf);
+	kfree(buf);
 }
 
-static int pl2303_open (struct usb_serial_port *port, struct file *filp)
+static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+{
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int c_cflag;
+	int bps;
+	long timeout;
+	wait_queue_t wait;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* wait for data to drain from the buffer */
+	spin_lock_irqsave(&priv->lock, flags);
+	timeout = PL2303_CLOSING_WAIT;
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&port->tty->write_wait, &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (pl2303_buf_data_avail(priv->buf) == 0 ||
+		    timeout == 0 || signal_pending(current) ||
+		    !usb_get_intfdata(port->serial->interface))	/* disconnect */
+			break;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		timeout = schedule_timeout(timeout);
+		spin_lock_irqsave(&priv->lock, flags);
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->tty->write_wait, &wait);
+	/* clear out any remaining data in the buffer */
+	pl2303_buf_clear(priv->buf);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* wait for characters to drain from the device */
+	/* (this is long enough for the entire 256 byte */
+	/* pl2303 hardware buffer to drain with no flow */
+	/* control for data rates of 1200 bps or more, */
+	/* for lower rates we should really know how much */
+	/* data is in the buffer to compute a delay */
+	/* that is not unnecessarily long) */
+	bps = tty_get_baud_rate(port->tty);
+	if (bps > 1200)
+		timeout = max((HZ*2560)/bps,HZ/10);
+	else
+		timeout = 2*HZ;
+	schedule_timeout_interruptible(timeout);
+
+	/* shutdown our urbs */
+	dbg("%s - shutting down urbs", __FUNCTION__);
+	usb_kill_urb(port->write_urb);
+	usb_kill_urb(port->read_urb);
+	usb_kill_urb(port->interrupt_in_urb);
+
+	if (port->tty) {
+		c_cflag = port->tty->termios->c_cflag;
+		if (c_cflag & HUPCL) {
+			/* drop DTR and RTS */
+			spin_lock_irqsave(&priv->lock, flags);
+			priv->line_control = 0;
+			spin_unlock_irqrestore(&priv->lock, flags);
+			set_control_lines(port->serial->dev, 0);
+		}
+	}
+}
+
+static int pl2303_open(struct usb_serial_port *port, struct file *filp)
 {
 	struct termios tmp_termios;
 	struct usb_serial *serial = port->serial;
@@ -568,98 +739,35 @@
 
 	/* Setup termios */
 	if (port->tty) {
-		pl2303_set_termios (port, &tmp_termios);
+		pl2303_set_termios(port, &tmp_termios);
 	}
 
 	//FIXME: need to assert RTS and DTR if CRTSCTS off
 
 	dbg("%s - submitting read urb", __FUNCTION__);
 	port->read_urb->dev = serial->dev;
-	result = usb_submit_urb (port->read_urb, GFP_KERNEL);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result) {
-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
-		pl2303_close (port, NULL);
+		dev_err(&port->dev, "%s - failed submitting read urb,"
+			" error %d\n", __FUNCTION__, result);
+		pl2303_close(port, NULL);
 		return -EPROTO;
 	}
 
 	dbg("%s - submitting interrupt urb", __FUNCTION__);
 	port->interrupt_in_urb->dev = serial->dev;
-	result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 	if (result) {
-		dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n", __FUNCTION__, result);
-		pl2303_close (port, NULL);
+		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+			" error %d\n", __FUNCTION__, result);
+		pl2303_close(port, NULL);
 		return -EPROTO;
 	}
 	return 0;
 }
 
-
-static void pl2303_close (struct usb_serial_port *port, struct file *filp)
-{
-	struct pl2303_private *priv = usb_get_serial_port_data(port);
-	unsigned long flags;
-	unsigned int c_cflag;
-	int bps;
-	long timeout;
-	wait_queue_t wait;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	/* wait for data to drain from the buffer */
-	spin_lock_irqsave(&priv->lock, flags);
-	timeout = PL2303_CLOSING_WAIT;
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&port->tty->write_wait, &wait);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (pl2303_buf_data_avail(priv->buf) == 0
-		|| timeout == 0 || signal_pending(current)
-		|| !usb_get_intfdata(port->serial->interface))	/* disconnect */
-			break;
-		spin_unlock_irqrestore(&priv->lock, flags);
-		timeout = schedule_timeout(timeout);
-		spin_lock_irqsave(&priv->lock, flags);
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->tty->write_wait, &wait);
-	/* clear out any remaining data in the buffer */
-	pl2303_buf_clear(priv->buf);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* wait for characters to drain from the device */
-	/* (this is long enough for the entire 256 byte */
-	/* pl2303 hardware buffer to drain with no flow */
-	/* control for data rates of 1200 bps or more, */
-	/* for lower rates we should really know how much */
-	/* data is in the buffer to compute a delay */
-	/* that is not unnecessarily long) */
-	bps = tty_get_baud_rate(port->tty);
-	if (bps > 1200)
-		timeout = max((HZ*2560)/bps,HZ/10);
-	else
-		timeout = 2*HZ;
-	schedule_timeout_interruptible(timeout);
-
-	/* shutdown our urbs */
-	dbg("%s - shutting down urbs", __FUNCTION__);
-	usb_kill_urb(port->write_urb);
-	usb_kill_urb(port->read_urb);
-	usb_kill_urb(port->interrupt_in_urb);
-
-	if (port->tty) {
-		c_cflag = port->tty->termios->c_cflag;
-		if (c_cflag & HUPCL) {
-			/* drop DTR and RTS */
-			spin_lock_irqsave(&priv->lock, flags);
-			priv->line_control = 0;
-			spin_unlock_irqrestore (&priv->lock, flags);
-			set_control_lines (port->serial->dev, 0);
-		}
-	}
-}
-
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-			    unsigned int set, unsigned int clear)
+static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
+			   unsigned int set, unsigned int clear)
 {
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -668,7 +776,7 @@
 	if (!usb_get_intfdata(port->serial->interface))
 		return -ENODEV;
 
-	spin_lock_irqsave (&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 	if (set & TIOCM_RTS)
 		priv->line_control |= CONTROL_RTS;
 	if (set & TIOCM_DTR)
@@ -678,12 +786,12 @@
 	if (clear & TIOCM_DTR)
 		priv->line_control &= ~CONTROL_DTR;
 	control = priv->line_control;
-	spin_unlock_irqrestore (&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return set_control_lines (port->serial->dev, control);
+	return set_control_lines(port->serial->dev, control);
 }
 
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
+static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
 {
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -696,10 +804,10 @@
 	if (!usb_get_intfdata(port->serial->interface))
 		return -ENODEV;
 
-	spin_lock_irqsave (&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 	mcr = priv->line_control;
 	status = priv->line_status;
-	spin_unlock_irqrestore (&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	result = ((mcr & CONTROL_DTR)		? TIOCM_DTR : 0)
 		  | ((mcr & CONTROL_RTS)	? TIOCM_RTS : 0)
@@ -721,22 +829,22 @@
 	unsigned int status;
 	unsigned int changed;
 
-	spin_lock_irqsave (&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 	prevstatus = priv->line_status;
-	spin_unlock_irqrestore (&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
 		interruptible_sleep_on(&priv->delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
-		
-		spin_lock_irqsave (&priv->lock, flags);
+
+		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
-		spin_unlock_irqrestore (&priv->lock, flags);
-		
+		spin_unlock_irqrestore(&priv->lock, flags);
+
 		changed=prevstatus^status;
-		
+
 		if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
 		    ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
 		    ((arg & TIOCM_CD)  && (changed & UART_DCD)) ||
@@ -749,7 +857,8 @@
 	return 0;
 }
 
-static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+			unsigned int cmd, unsigned long arg)
 {
 	dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
 
@@ -766,7 +875,7 @@
 	return -ENOIOCTLCMD;
 }
 
-static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
+static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
 {
 	struct usb_serial *serial = port->serial;
 	u16 state;
@@ -780,15 +889,14 @@
 		state = BREAK_ON;
 	dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
 
-	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
-				  0, NULL, 0, 100);
+	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+				 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+				 0, NULL, 0, 100);
 	if (result)
 		dbg("%s - error sending break = %d", __FUNCTION__, result);
 }
 
-
-static void pl2303_shutdown (struct usb_serial *serial)
+static void pl2303_shutdown(struct usb_serial *serial)
 {
 	int i;
 	struct pl2303_private *priv;
@@ -802,7 +910,7 @@
 			kfree(priv);
 			usb_set_serial_port_data(serial->port[i], NULL);
 		}
-	}		
+	}
 }
 
 static void pl2303_update_line_status(struct usb_serial_port *port,
@@ -814,29 +922,33 @@
 	unsigned long flags;
 	u8 status_idx = UART_STATE;
 	u8 length = UART_STATE + 1;
+	u16 idv, idp;
 
-	if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
-	    (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 ||
-	     le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_SX1 ||
-	     le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X75)) {
-		length = 1;
-		status_idx = 0;
+	idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
+	idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);
+
+
+	if (idv == SIEMENS_VENDOR_ID) {
+		if (idp == SIEMENS_PRODUCT_ID_X65 ||
+		    idp == SIEMENS_PRODUCT_ID_SX1 ||
+		    idp == SIEMENS_PRODUCT_ID_X75) {
+
+			length = 1;
+			status_idx = 0;
+		}
 	}
 
 	if (actual_length < length)
-		goto exit;
+		return;
 
         /* Save off the uart status for others to look at */
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->line_status = data[status_idx];
 	spin_unlock_irqrestore(&priv->lock, flags);
-	wake_up_interruptible (&priv->delta_msr_wait);
-
-exit:
-	return;
+	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 pt_regs *regs)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -853,25 +965,29 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+		    urb->status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+		    urb->status);
 		goto exit;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+			      urb->actual_length, urb->transfer_buffer);
+
 	pl2303_update_line_status(port, data, actual_length);
 
 exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
+	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status)
-		dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+		dev_err(&urb->dev->dev,
+			"%s - usb_submit_urb failed with result %d\n",
 			__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 pt_regs *regs)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -892,20 +1008,25 @@
 			return;
 		}
 		if (urb->status == -EPROTO) {
-			/* PL2303 mysteriously fails with -EPROTO reschedule the read */
-			dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+			/* PL2303 mysteriously fails with -EPROTO reschedule
+			 * the read */
+			dbg("%s - caught -EPROTO, resubmitting the urb",
+			    __FUNCTION__);
 			urb->status = 0;
 			urb->dev = port->serial->dev;
 			result = usb_submit_urb(urb, GFP_ATOMIC);
 			if (result)
-				dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+				dev_err(&urb->dev->dev, "%s - failed"
+					" resubmitting read urb, error %d\n",
+					__FUNCTION__, result);
 			return;
 		}
 		dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+			      urb->actual_length, data);
 
 	/* get tty_flag from status */
 	tty_flag = TTY_NORMAL;
@@ -914,7 +1035,7 @@
 	status = priv->line_status;
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	wake_up_interruptible (&priv->delta_msr_wait);
+	wake_up_interruptible(&priv->delta_msr_wait);
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
@@ -933,8 +1054,8 @@
 		if (status & UART_OVERRUN_ERROR)
 			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 		for (i = 0; i < urb->actual_length; ++i)
-			tty_insert_flip_char (tty, data[i], tty_flag);
-		tty_flip_buffer_push (tty);
+			tty_insert_flip_char(tty, data[i], tty_flag);
+		tty_flip_buffer_push(tty);
 	}
 
 	/* Schedule the next read _if_ we are still open */
@@ -942,15 +1063,14 @@
 		urb->dev = port->serial->dev;
 		result = usb_submit_urb(urb, GFP_ATOMIC);
 		if (result)
-			dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+			dev_err(&urb->dev->dev, "%s - failed resubmitting"
+				" read urb, error %d\n", __FUNCTION__, result);
 	}
 
 	return;
 }
 
-
-
-static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void pl2303_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -966,18 +1086,21 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+		    urb->status);
 		priv->write_urb_in_use = 0;
 		return;
 	default:
 		/* error in the urb, so we have to resubmit it */
 		dbg("%s - Overflow in write", __FUNCTION__);
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
+		    urb->status);
 		port->write_urb->transfer_buffer_length = 1;
 		port->write_urb->dev = port->serial->dev;
-		result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result)
-			dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result);
+			dev_err(&urb->dev->dev, "%s - failed resubmitting write"
+				" urb, error %d\n", __FUNCTION__, result);
 		else
 			return;
 	}
@@ -988,191 +1111,38 @@
 	pl2303_send(port);
 }
 
+/* All of the device info needed for the PL2303 SIO serial converter */
+static struct usb_serial_driver pl2303_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"pl2303",
+	},
+	.id_table =		id_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			pl2303_open,
+	.close =		pl2303_close,
+	.write =		pl2303_write,
+	.ioctl =		pl2303_ioctl,
+	.break_ctl =		pl2303_break_ctl,
+	.set_termios =		pl2303_set_termios,
+	.tiocmget =		pl2303_tiocmget,
+	.tiocmset =		pl2303_tiocmset,
+	.read_bulk_callback =	pl2303_read_bulk_callback,
+	.read_int_callback =	pl2303_read_int_callback,
+	.write_bulk_callback =	pl2303_write_bulk_callback,
+	.write_room =		pl2303_write_room,
+	.chars_in_buffer =	pl2303_chars_in_buffer,
+	.attach =		pl2303_startup,
+	.shutdown =		pl2303_shutdown,
+};
 
-/*
- * pl2303_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
-{
-
-	struct pl2303_buf *pb;
-
-
-	if (size == 0)
-		return NULL;
-
-	pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
-	if (pb == NULL)
-		return NULL;
-
-	pb->buf_buf = kmalloc(size, GFP_KERNEL);
-	if (pb->buf_buf == NULL) {
-		kfree(pb);
-		return NULL;
-	}
-
-	pb->buf_size = size;
-	pb->buf_get = pb->buf_put = pb->buf_buf;
-
-	return pb;
-
-}
-
-
-/*
- * pl2303_buf_free
- *
- * Free the buffer and all associated memory.
- */
-
-static void pl2303_buf_free(struct pl2303_buf *pb)
-{
-	if (pb) {
-		kfree(pb->buf_buf);
-		kfree(pb);
-	}
-}
-
-
-/*
- * pl2303_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-
-static void pl2303_buf_clear(struct pl2303_buf *pb)
-{
-	if (pb != NULL)
-		pb->buf_get = pb->buf_put;
-		/* equivalent to a get of all data available */
-}
-
-
-/*
- * pl2303_buf_data_avail
- *
- * Return the number of bytes of data available in the circular
- * buffer.
- */
-
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
-{
-	if (pb != NULL)
-		return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
-	else
-		return 0;
-}
-
-
-/*
- * pl2303_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
-{
-	if (pb != NULL)
-		return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
-	else
-		return 0;
-}
-
-
-/*
- * pl2303_buf_put
- *
- * Copy data data from a user buffer and put it into the circular buffer.
- * Restrict to the amount of space available.
- *
- * Return the number of bytes copied.
- */
-
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
-	unsigned int count)
-{
-
-	unsigned int len;
-
-
-	if (pb == NULL)
-		return 0;
-
-	len  = pl2303_buf_space_avail(pb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = pb->buf_buf + pb->buf_size - pb->buf_put;
-	if (count > len) {
-		memcpy(pb->buf_put, buf, len);
-		memcpy(pb->buf_buf, buf+len, count - len);
-		pb->buf_put = pb->buf_buf + count - len;
-	} else {
-		memcpy(pb->buf_put, buf, count);
-		if (count < len)
-			pb->buf_put += count;
-		else /* count == len */
-			pb->buf_put = pb->buf_buf;
-	}
-
-	return count;
-
-}
-
-
-/*
- * pl2303_buf_get
- *
- * Get data from the circular buffer and copy to the given buffer.
- * Restrict to the amount of data available.
- *
- * Return the number of bytes copied.
- */
-
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
-	unsigned int count)
-{
-
-	unsigned int len;
-
-
-	if (pb == NULL)
-		return 0;
-
-	len = pl2303_buf_data_avail(pb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = pb->buf_buf + pb->buf_size - pb->buf_get;
-	if (count > len) {
-		memcpy(buf, pb->buf_get, len);
-		memcpy(buf+len, pb->buf_buf, count - len);
-		pb->buf_get = pb->buf_buf + count - len;
-	} else {
-		memcpy(buf, pb->buf_get, count);
-		if (count < len)
-			pb->buf_get += count;
-		else /* count == len */
-			pb->buf_get = pb->buf_buf;
-	}
-
-	return count;
-
-}
-
-static int __init pl2303_init (void)
+static int __init pl2303_init(void)
 {
 	int retval;
+
 	retval = usb_serial_register(&pl2303_device);
 	if (retval)
 		goto failed_usb_serial_register;
@@ -1187,14 +1157,12 @@
 	return retval;
 }
 
-
-static void __exit pl2303_exit (void)
+static void __exit pl2303_exit(void)
 {
-	usb_deregister (&pl2303_driver);
-	usb_serial_deregister (&pl2303_device);
+	usb_deregister(&pl2303_driver);
+	usb_serial_deregister(&pl2303_device);
 }
 
-
 module_init(pl2303_init);
 module_exit(pl2303_exit);
 
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 55195e7..65a50396 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -89,3 +89,11 @@
 /* Belkin "F5U257" Serial Adapter */
 #define BELKIN_VENDOR_ID	0x050d
 #define BELKIN_PRODUCT_ID	0x0257
+
+/* Alcor Micro Corp. USB 2.0 TO RS-232 */
+#define ALCOR_VENDOR_ID		0x058F
+#define ALCOR_PRODUCT_ID	0x9720
+
+/* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
+#define HUAWEI_VENDOR_ID	0x12d1
+#define HUAWEI_PRODUCT_ID	0x1001
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 789771e..1e07dfa 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -298,14 +298,14 @@
 		dbg ("%s - write request of 0 bytes", __FUNCTION__);
 		return (0);
 	}
-	spin_lock(&port->lock);
+	spin_lock_bh(&port->lock);
 	if (port->write_urb_busy) {
-		spin_unlock(&port->lock);
+		spin_unlock_bh(&port->lock);
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
 	}
 	port->write_urb_busy = 1;
-	spin_unlock(&port->lock);
+	spin_unlock_bh(&port->lock);
 
 	packet_length = port->bulk_out_size;	// get max packetsize
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index e06a41b..0222d92 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -676,33 +676,29 @@
 	iface_desc = interface->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
-		
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
+
+		if (usb_endpoint_is_bulk_in(endpoint)) {
 			/* we found a bulk in endpoint */
 			dbg("found bulk in on endpoint %d", i);
 			bulk_in_endpoint[num_bulk_in] = endpoint;
 			++num_bulk_in;
 		}
 
-		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
+		if (usb_endpoint_is_bulk_out(endpoint)) {
 			/* we found a bulk out endpoint */
 			dbg("found bulk out on endpoint %d", i);
 			bulk_out_endpoint[num_bulk_out] = endpoint;
 			++num_bulk_out;
 		}
-		
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x03)) {
+
+		if (usb_endpoint_is_int_in(endpoint)) {
 			/* we found a interrupt in endpoint */
 			dbg("found interrupt in on endpoint %d", i);
 			interrupt_in_endpoint[num_interrupt_in] = endpoint;
 			++num_interrupt_in;
 		}
 
-		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-		    ((endpoint->bmAttributes & 3) == 0x03)) {
+		if (usb_endpoint_is_int_out(endpoint)) {
 			/* we found an interrupt out endpoint */
 			dbg("found interrupt out on endpoint %d", i);
 			interrupt_out_endpoint[num_interrupt_out] = endpoint;
@@ -716,14 +712,15 @@
 	if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
 	     (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
 	    ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
-	     (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID))) {
+	     (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
+	    ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
+	     (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
 		if (interface != dev->actconfig->interface[0]) {
 			/* check out the endpoints of the other interface*/
 			iface_desc = dev->actconfig->interface[0]->cur_altsetting;
 			for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 				endpoint = &iface_desc->endpoint[i].desc;
-				if ((endpoint->bEndpointAddress & 0x80) &&
-				    ((endpoint->bmAttributes & 3) == 0x03)) {
+				if (usb_endpoint_is_int_in(endpoint)) {
 					/* we found a interrupt in endpoint */
 					dbg("found interrupt in for Prolific device on separate interface");
 					interrupt_in_endpoint[num_interrupt_in] = endpoint;
@@ -937,7 +934,10 @@
 
 		snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
 		dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
-		device_register (&port->dev);
+		retval = device_register(&port->dev);
+		if (retval)
+			dev_err(&port->dev, "Error registering port device, "
+				"continuing\n");
 	}
 
 	usb_serial_console_init (debug, minor);
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index be9eec2..86e48c4 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -135,6 +135,18 @@
 	  this input in any keybinding software. (e.g. gnome's keyboard short-
 	  cuts)
 
+config USB_STORAGE_KARMA
+	bool "Support for Rio Karma music player"
+	depends on USB_STORAGE
+	help
+	  Say Y here to include additional code to support the Rio Karma
+	  USB interface.
+
+	  This code places the Rio Karma into mass storage mode, enabling
+	  it to be mounted as an ordinary filesystem. Performing an eject
+	  on the resulting scsi device node returns the Karma to normal
+	  operation.
+
 config USB_LIBUSUAL
 	bool "The shared table of common (or usual) storage devices"
 	depends on USB
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 8cbba22..023969b 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -20,6 +20,7 @@
 usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)	+= karma.o
 
 usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
 			initializers.o $(usb-storage-obj-y)
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index ab173b3..5b06f92 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -45,12 +45,6 @@
 #include "debug.h"
 #include "transport.h"
 
-#define RIO_MSC 0x08
-#define RIOP_INIT "RIOP\x00\x01\x08"
-#define RIOP_INIT_LEN 7
-#define RIO_SEND_LEN 40
-#define RIO_RECV_LEN 0x200
-
 /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
  * mode */
 int usb_stor_euscsi_init(struct us_data *us)
@@ -97,70 +91,3 @@
 
 	return (res ? -1 : 0);
 }
-
-/* Place the Rio Karma into mass storage mode.
- *
- * The initialization begins by sending 40 bytes starting
- * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte
- * packet with the high four bits set and everything else null.
- *
- * Next, we send RIOP\x80\x00\x08\x00.  Each time, a 512 byte response
- * must be read, but we must loop until byte 5 in the response is 0x08,
- * indicating success.  */
-int rio_karma_init(struct us_data *us)
-{
-	int result, partial;
-	char *recv;
-	unsigned long timeout;
-
-	// us->iobuf is big enough to hold cmd but not receive
-	if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL)))
-		goto die_nomem;
-
-	US_DEBUGP("Initializing Karma...\n");
-
-	memset(us->iobuf, 0, RIO_SEND_LEN);
-	memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN);
-
-	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-		us->iobuf, RIO_SEND_LEN, &partial);
-	if (result != USB_STOR_XFER_GOOD)
-		goto die;
-
-	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-		recv, RIO_RECV_LEN, &partial);
-	if (result != USB_STOR_XFER_GOOD)
-		goto die;
-
-	us->iobuf[4] = 0x80;
-	us->iobuf[5] = 0;
-	timeout = jiffies + msecs_to_jiffies(3000);
-	for (;;) {
-		US_DEBUGP("Sending init command\n");
-		result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-			us->iobuf, RIO_SEND_LEN, &partial);
-		if (result != USB_STOR_XFER_GOOD)
-			goto die;
-
-		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-			recv, RIO_RECV_LEN, &partial);
-		if (result != USB_STOR_XFER_GOOD)
-			goto die;
-
-		if (recv[5] == RIO_MSC)
-			break;
-		if (time_after(jiffies, timeout))
-			goto die;
-		msleep(10);
-	}
-	US_DEBUGP("Karma initialized.\n");
-	kfree(recv);
-	return 0;
-
-die:
-	kfree(recv);
-die_nomem:
-	US_DEBUGP("Could not initialize karma.\n");
-	return USB_STOR_TRANSPORT_FAILED;
-}
-
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 927f778..e2967a4 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -47,4 +47,3 @@
 /* This function is required to activate all four slots on the UCR-61S2B
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
-int rio_karma_init(struct us_data *us);
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
new file mode 100644
index 0000000..0d79ae5
--- /dev/null
+++ b/drivers/usb/storage/karma.c
@@ -0,0 +1,155 @@
+/* Driver for Rio Karma
+ *
+ *   (c) 2006 Bob Copeland <me@bobcopeland.com>
+ *   (c) 2006 Keith Bennett <keith@mcs.st-and.ac.uk>
+ *
+ * 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 <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "debug.h"
+#include "karma.h"
+
+#define RIO_PREFIX "RIOP\x00"
+#define RIO_PREFIX_LEN 5
+#define RIO_SEND_LEN 40
+#define RIO_RECV_LEN 0x200
+
+#define RIO_ENTER_STORAGE 0x1
+#define RIO_LEAVE_STORAGE 0x2
+#define RIO_RESET 0xC
+
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *);
+
+struct karma_data {
+	int in_storage;
+	char *recv;
+};
+
+/*
+ * Send commands to Rio Karma.
+ *
+ * For each command we send 40 bytes starting 'RIOP\0' followed by
+ * the command number and a sequence number, which the device will ack
+ * with a 512-byte packet with the high four bits set and everything
+ * else null.  Then we send 'RIOP\x80' followed by a zero and the
+ * sequence number, until byte 5 in the response repeats the sequence
+ * number.
+ */
+static int rio_karma_send_command(char cmd, struct us_data *us)
+{
+	int result, partial;
+	unsigned long timeout;
+	static unsigned char seq = 1;
+	struct karma_data *data = (struct karma_data *) us->extra;
+
+	US_DEBUGP("karma: sending command %04x\n", cmd);
+	memset(us->iobuf, 0, RIO_SEND_LEN);
+	memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
+	us->iobuf[5] = cmd;
+	us->iobuf[6] = seq;
+
+	timeout = jiffies + msecs_to_jiffies(6000);
+	for (;;) {
+		result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+			us->iobuf, RIO_SEND_LEN, &partial);
+		if (result != USB_STOR_XFER_GOOD)
+			goto err;
+
+		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+			data->recv, RIO_RECV_LEN, &partial);
+		if (result != USB_STOR_XFER_GOOD)
+			goto err;
+
+		if (data->recv[5] == seq)
+			break;
+
+		if (time_after(jiffies, timeout))
+			goto err;
+
+		us->iobuf[4] = 0x80;
+		us->iobuf[5] = 0;
+		msleep(50);
+	}
+
+	seq++;
+	if (seq == 0)
+		seq = 1;
+
+	US_DEBUGP("karma: sent command %04x\n", cmd);
+	return 0;
+err:
+	US_DEBUGP("karma: command %04x failed\n", cmd);
+	return USB_STOR_TRANSPORT_FAILED;
+}
+
+/*
+ * Trap START_STOP and READ_10 to leave/re-enter storage mode.
+ * Everything else is propagated to the normal bulk layer.
+ */
+int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+	int ret;
+	struct karma_data *data = (struct karma_data *) us->extra;
+
+	if (srb->cmnd[0] == READ_10 && !data->in_storage) {
+		ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
+		if (ret)
+			return ret;
+
+		data->in_storage = 1;
+		return usb_stor_Bulk_transport(srb, us);
+	} else if (srb->cmnd[0] == START_STOP) {
+		ret = rio_karma_send_command(RIO_LEAVE_STORAGE, us);
+		if (ret)
+			return ret;
+
+		data->in_storage = 0;
+		return rio_karma_send_command(RIO_RESET, us);
+	}
+	return usb_stor_Bulk_transport(srb, us);
+}
+
+static void rio_karma_destructor(void *extra)
+{
+	struct karma_data *data = (struct karma_data *) extra;
+	kfree(data->recv);
+}
+
+int rio_karma_init(struct us_data *us)
+{
+	int ret = 0;
+	struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
+	if (!data)
+		goto out;
+
+	data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO);
+	if (!data->recv) {
+		kfree(data);
+		goto out;
+	}
+
+	us->extra = data;
+	us->extra_destructor = rio_karma_destructor;
+	ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
+	data->in_storage = (ret == 0);
+out:
+	return ret;
+}
diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h
new file mode 100644
index 0000000..8a60972
--- /dev/null
+++ b/drivers/usb/storage/karma.h
@@ -0,0 +1,7 @@
+#ifndef _KARMA_USB_H
+#define _KARMA_USB_H
+
+extern int rio_karma_init(struct us_data *us);
+extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us);
+
+#endif
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index b1ec4a7..599ad10 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -8,6 +8,7 @@
 #include <linux/usb.h>
 #include <linux/usb_usual.h>
 #include <linux/vmalloc.h>
+#include <linux/kthread.h>
 
 /*
  */
@@ -117,7 +118,7 @@
 			 const struct usb_device_id *id)
 {
 	unsigned long type;
-	int rc;
+	struct task_struct* task;
 	unsigned long flags;
 
 	type = USB_US_TYPE(id->driver_info);
@@ -132,8 +133,9 @@
 	stat[type].fls |= USU_MOD_FL_THREAD;
 	spin_unlock_irqrestore(&usu_lock, flags);
 
-	rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
-	if (rc < 0) {
+	task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type);
+	if (IS_ERR(task)) {
+		int rc = PTR_ERR(task);
 		printk(KERN_WARNING "libusual: "
 		    "Unable to start the thread for %s: %d\n",
 		    bias_names[type], rc);
@@ -175,8 +177,6 @@
 	int rc;
 	unsigned long flags;
 
-	daemonize("libusual_%d", type);	/* "usb-storage" is kinda too long */
-
 	/* A completion does not work here because it's counted. */
 	down(&usu_init_notify);
 	up(&usu_init_notify);
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 313920d..f843a0b 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -135,6 +135,7 @@
 	struct usb_onetouch *onetouch;
 	struct input_dev *input_dev;
 	int pipe, maxp;
+	int error = -ENOMEM;
 
 	interface = ss->pusb_intf->cur_altsetting;
 
@@ -211,15 +212,18 @@
 	ss->suspend_resume_hook = usb_onetouch_pm_hook;
 #endif
 
-	input_register_device(onetouch->dev);
+	error = input_register_device(onetouch->dev);
+	if (error)
+		goto fail3;
 
 	return 0;
 
+ fail3:	usb_free_urb(onetouch->irq);
  fail2:	usb_buffer_free(udev, ONETOUCH_PKT_LEN,
 			onetouch->data, onetouch->data_dma);
  fail1:	kfree(onetouch);
 	input_free_device(input_dev);
-	return -ENOMEM;
+	return error;
 }
 
 void onetouch_release_input(void *onetouch_)
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a4b7df9..e1072d5 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -72,12 +72,27 @@
 
 static int slave_alloc (struct scsi_device *sdev)
 {
+	struct us_data *us = host_to_us(sdev->host);
+
 	/*
 	 * Set the INQUIRY transfer length to 36.  We don't use any of
 	 * the extra data and many devices choke if asked for more or
 	 * less than 36 bytes.
 	 */
 	sdev->inquiry_len = 36;
+
+	/*
+	 * The UFI spec treates the Peripheral Qualifier bits in an
+	 * INQUIRY result as reserved and requires devices to set them
+	 * to 0.  However the SCSI spec requires these bits to be set
+	 * to 3 to indicate when a LUN is not present.
+	 *
+	 * Let the scanning code know if this target merely sets
+	 * Peripheral Device Type to 0x1f to indicate no LUN.
+	 */
+	if (us->subclass == US_SC_UFI)
+		sdev->sdev_target->pdt_1f_for_no_lun = 1;
+
 	return 0;
 }
 
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index d6acc92..f23514c 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -294,11 +294,6 @@
 			return USB_STOR_XFER_ERROR;
 		return USB_STOR_XFER_STALLED;
 
-	/* timeout or excessively long NAK */
-	case -ETIMEDOUT:
-		US_DEBUGP("-- timeout or NAK\n");
-		return USB_STOR_XFER_ERROR;
-
 	/* babble - the device tried to send more than we wanted to read */
 	case -EOVERFLOW:
 		US_DEBUGP("-- babble\n");
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index b130e17..c9a8d50 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -152,6 +152,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
+/* Reported by Jon Hart <Jon.Hart@web.de> */
+UNUSUAL_DEV(  0x0421, 0x0434, 0x0100, 0x0100,
+		"Nokia",
+		"E60",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and
  * Einar Th. Einarsson <einarthered@gmail.com> */
 UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,
@@ -218,10 +225,12 @@
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_NOT_LOCKABLE ),
 
+#ifdef CONFIG_USB_STORAGE_KARMA
 UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
 		"Rio",
 		"Rio Karma",
-		US_SC_SCSI, US_PR_BULK, rio_karma_init, 0),
+		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+#endif
 
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
@@ -631,6 +640,13 @@
 		"Digital Camera EX-20 DSC",
 		US_SC_8070, US_PR_DEVICE, NULL, 0 ),
 
+/* Reported by <Hendryk.Pfeiffer@gmx.de> */
+UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
+		"LaCie",
+		"DVD+-RW",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_GO_SLOW ),
+
 /* Submitted by Joel Bourquard <numlock@freesurf.ch>
  * Some versions of this device need the SubClass and Protocol overrides
  * while others don't.
@@ -1254,6 +1270,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT ),
 
+/* 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 Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
 		"Sony Ericsson",
@@ -1261,6 +1284,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/storage/usb.c b/drivers/usb/storage/usb.c
index 8d7bdcb..b8d6031 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -98,6 +98,9 @@
 #ifdef CONFIG_USB_STORAGE_ALAUDA
 #include "alauda.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_KARMA
+#include "karma.h"
+#endif
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -646,6 +649,14 @@
 		break;
 #endif
 
+#ifdef CONFIG_USB_STORAGE_KARMA
+	case US_PR_KARMA:
+		us->transport_name = "Rio Karma/Bulk";
+		us->transport = rio_karma_transport;
+		us->transport_reset = usb_stor_Bulk_reset;
+		break;
+#endif
+
 	default:
 		return -EIO;
 	}
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index b362039..1b51d31 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -1,5 +1,5 @@
 /*
- * USB Skeleton driver - 2.0
+ * USB Skeleton driver - 2.2
  *
  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
  *
@@ -7,9 +7,8 @@
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
  *
- * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
- * but has been rewritten to be easy to read and use, as no locks are now
- * needed anymore.
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
+ * but has been rewritten to be easier to read and use.
  *
  */
 
@@ -21,6 +20,7 @@
 #include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
+#include <linux/mutex.h>
 
 
 /* Define these values to match your devices */
@@ -32,38 +32,39 @@
 	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
-MODULE_DEVICE_TABLE (usb, skel_table);
+MODULE_DEVICE_TABLE(usb, skel_table);
 
 
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE	192
 
 /* our private defines. if this grows any larger, use your own .h file */
-#define MAX_TRANSFER		( PAGE_SIZE - 512 )
+#define MAX_TRANSFER		(PAGE_SIZE - 512)
 #define WRITES_IN_FLIGHT	8
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-	struct usb_device *	udev;			/* the usb device for this device */
-	struct usb_interface *	interface;		/* the interface for this device */
+	struct usb_device       *dev;			/* the usb device for this device */
+	struct usb_interface    *interface;		/* the interface for this device */
 	struct semaphore	limit_sem;		/* limiting the number of writes in progress */
-	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */
+	unsigned char           *bulk_in_buffer;	/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
 	struct kref		kref;
+	struct mutex		io_mutex;		/* synchronize I/O with disconnect */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
 static struct usb_driver skel_driver;
 
 static void skel_delete(struct kref *kref)
-{	
+{
 	struct usb_skel *dev = to_skel_dev(kref);
 
 	usb_put_dev(dev->udev);
-	kfree (dev->bulk_in_buffer);
-	kfree (dev);
+	kfree(dev->bulk_in_buffer);
+	kfree(dev);
 }
 
 static int skel_open(struct inode *inode, struct file *file)
@@ -89,6 +90,11 @@
 		goto exit;
 	}
 
+	/* prevent the device from being autosuspended */
+	retval = usb_autopm_get_interface(interface);
+	if (retval)
+		goto exit;
+
 	/* increment our usage count for the device */
 	kref_get(&dev->kref);
 
@@ -107,6 +113,12 @@
 	if (dev == NULL)
 		return -ENODEV;
 
+	/* allow the device to be autosuspended */
+	mutex_lock(&dev->io_mutex);
+	if (dev->interface)
+		usb_autopm_put_interface(dev->interface);
+	mutex_unlock(&dev->io_mutex);
+
 	/* decrement the count on our device */
 	kref_put(&dev->kref, skel_delete);
 	return 0;
@@ -115,11 +127,17 @@
 static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct usb_skel *dev;
-	int retval = 0;
+	int retval;
 	int bytes_read;
 
 	dev = (struct usb_skel *)file->private_data;
-	
+
+	mutex_lock(&dev->io_mutex);
+	if (!dev->interface) {		/* disconnect() was called */
+		retval = -ENODEV;
+		goto exit;
+	}
+
 	/* do a blocking bulk read to get data from the device */
 	retval = usb_bulk_msg(dev->udev,
 			      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
@@ -135,6 +153,8 @@
 			retval = bytes_read;
 	}
 
+exit:
+	mutex_unlock(&dev->io_mutex);
 	return retval;
 }
 
@@ -145,16 +165,16 @@
 	dev = (struct usb_skel *)urb->context;
 
 	/* sync/async unlink faults aren't errors */
-	if (urb->status && 
-	    !(urb->status == -ENOENT || 
+	if (urb->status &&
+	    !(urb->status == -ENOENT ||
 	      urb->status == -ECONNRESET ||
 	      urb->status == -ESHUTDOWN)) {
-		dbg("%s - nonzero write bulk status received: %d",
+		err("%s - nonzero write bulk status received: %d",
 		    __FUNCTION__, urb->status);
 	}
 
 	/* free up our allocated buffer */
-	usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length,
 			urb->transfer_buffer, urb->transfer_dma);
 	up(&dev->limit_sem);
 }
@@ -179,6 +199,12 @@
 		goto exit;
 	}
 
+	mutex_lock(&dev->io_mutex);
+	if (!dev->interface) {		/* disconnect() was called */
+		retval = -ENODEV;
+		goto error;
+	}
+
 	/* create a urb, and a buffer for it, and copy the data to the urb */
 	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
@@ -213,17 +239,22 @@
 	/* release our reference to this urb, the USB core will eventually free it entirely */
 	usb_free_urb(urb);
 
-exit:
+	mutex_unlock(&dev->io_mutex);
 	return writesize;
 
 error:
-	usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
-	usb_free_urb(urb);
+	if (urb) {
+		usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
+		usb_free_urb(urb);
+	}
+	mutex_unlock(&dev->io_mutex);
 	up(&dev->limit_sem);
+
+exit:
 	return retval;
 }
 
-static struct file_operations skel_fops = {
+static const struct file_operations skel_fops = {
 	.owner =	THIS_MODULE,
 	.read =		skel_read,
 	.write =	skel_write,
@@ -231,7 +262,7 @@
 	.release =	skel_release,
 };
 
-/* 
+/*
  * usb class driver info in order to get a minor number from the usb core,
  * and to have the device registered with the driver core
  */
@@ -243,7 +274,7 @@
 
 static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-	struct usb_skel *dev = NULL;
+	struct usb_skel *dev;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	size_t buffer_size;
@@ -252,12 +283,13 @@
 
 	/* allocate memory for our device state and initialize it */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL) {
+	if (!dev) {
 		err("Out of memory");
 		goto error;
 	}
 	kref_init(&dev->kref);
 	sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+	mutex_init(&dev->io_mutex);
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
@@ -269,10 +301,7 @@
 		endpoint = &iface_desc->endpoint[i].desc;
 
 		if (!dev->bulk_in_endpointAddr &&
-		    ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-					== USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-					== USB_ENDPOINT_XFER_BULK)) {
+		    usb_endpoint_is_bulk_in(endpoint)) {
 			/* we found a bulk in endpoint */
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			dev->bulk_in_size = buffer_size;
@@ -285,10 +314,7 @@
 		}
 
 		if (!dev->bulk_out_endpointAddr &&
-		    ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-					== USB_DIR_OUT) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-					== USB_ENDPOINT_XFER_BULK)) {
+		    usb_endpoint_is_bulk_out(endpoint)) {
 			/* we found a bulk out endpoint */
 			dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
 		}
@@ -334,6 +360,11 @@
 	/* give back our minor */
 	usb_deregister_dev(interface, &skel_class);
 
+	/* prevent more I/O from starting */
+	mutex_lock(&dev->io_mutex);
+	dev->interface = NULL;
+	mutex_unlock(&dev->io_mutex);
+
 	unlock_kernel();
 
 	/* decrement our usage count */
@@ -367,7 +398,7 @@
 	usb_deregister(&skel_driver);
 }
 
-module_init (usb_skel_init);
-module_exit (usb_skel_exit);
+module_init(usb_skel_init);
+module_exit(usb_skel_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index caf1eca..628571c 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -33,19 +33,19 @@
 
 static void locomolcd_on(int comadj)
 {
-	locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1);
+	locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 1);
 	mdelay(2);
 
-	locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1);
+	locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 1);
 	mdelay(2);
 
 	locomo_m62332_senddata(locomolcd_dev, comadj, 0);
 	mdelay(5);
 
-	locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1);
+	locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 1);
 	mdelay(10);
 
 	/* TFTCRST | CPSOUT=0 | CPSEN */
@@ -58,8 +58,8 @@
 	locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
 	mdelay(10);
 
-	locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1);
+	locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 1);
 }
 
 static void locomolcd_off(int comadj)
@@ -68,16 +68,16 @@
 	locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
 	mdelay(1);
 
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
 	mdelay(110);
 
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
 	mdelay(700);
 
 	/* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
 	locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
-	locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
 }
 
 void locomolcd_power(int on)
@@ -167,14 +167,14 @@
 #define locomolcd_resume	NULL
 #endif
 
-static int locomolcd_probe(struct locomo_dev *dev)
+static int locomolcd_probe(struct locomo_dev *ldev)
 {
 	unsigned long flags;
 
 	local_irq_save(flags);
-	locomolcd_dev = dev;
+	locomolcd_dev = ldev;
 
-	locomo_gpio_set_dir(dev, LOCOMO_GPIO_FL_VR, 0);
+	locomo_gpio_set_dir(ldev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
 
 	/* the poodle_lcd_power function is called for the first time
 	 * from fs_initcall, which is before locomo is activated.
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 22f7ccd..0f62804 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -460,8 +460,10 @@
 
 	ret = v9fs_mux_global_init();
 	if (!ret)
-		ret = register_filesystem(&v9fs_fs_type);
-
+		return ret;
+	ret = register_filesystem(&v9fs_fs_type);
+	if (!ret)
+		v9fs_mux_global_exit();
 	return ret;
 }
 
diff --git a/fs/Kconfig b/fs/Kconfig
index d311198..4fd9efa 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -881,6 +881,19 @@
 
 	  See <file:Documentation/filesystems/tmpfs.txt> for details.
 
+config TMPFS_POSIX_ACL
+	bool "Tmpfs POSIX Access Control Lists"
+	depends on TMPFS
+	select GENERIC_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 HUGETLBFS
 	bool "HugeTLB file system support"
 	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
@@ -1940,6 +1953,10 @@
 
 	  If unsure, say N.
 
+config GENERIC_ACL
+	bool
+	select FS_POSIX_ACL
+
 endmenu
 
 menu "Partition Types"
diff --git a/fs/Makefile b/fs/Makefile
index 8913542..46b8cfe 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o
 obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o xattr_acl.o
 obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
+obj-$(CONFIG_GENERIC_ACL)	+= generic_acl.o
 
 obj-$(CONFIG_QUOTA)		+= dquot.o
 obj-$(CONFIG_QFMT_V1)		+= quota_v1.o
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 101d21b..86463ec 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -775,6 +775,7 @@
  * first item
  */
 static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
+	__acquires(m->private->sv_lock)
 {
 	struct list_head *_p;
 	struct afs_cell *cell = m->private;
@@ -823,6 +824,7 @@
  * clean up after reading from the cells list
  */
 static void afs_proc_cell_servers_stop(struct seq_file *p, void *v)
+	__releases(p->private->sv_lock)
 {
 	struct afs_cell *cell = p->private;
 
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 27e17f9..563ef9d 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -281,9 +281,6 @@
 
 		DPRINTK("mount done status=%d", status);
 
-		if (status && dentry->d_inode)
-			return status; /* Try to get the kernel to invalidate this dentry */
-
 		/* Turn this into a real negative dentry? */
 		if (status == -ENOENT) {
 			spin_lock(&dentry->d_lock);
@@ -359,7 +356,7 @@
 	 * don't try to mount it again.
 	 */
 	spin_lock(&dcache_lock);
-	if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
+	if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
 		spin_unlock(&dcache_lock);
 
 		status = try_to_fill_dentry(dentry, 0);
@@ -540,6 +537,9 @@
 			    return ERR_PTR(-ERESTARTNOINTR);
 			}
 		}
+		spin_lock(&dentry->d_lock);
+		dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
+		spin_unlock(&dentry->d_lock);
 	}
 
 	/*
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index f312103..517e111 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -278,6 +278,13 @@
 		return -ENOEXEC;
 	}
 
+	/*
+	 * Requires a mmap handler. This prevents people from using a.out
+	 * as part of an exploit attack against /proc-related vulnerabilities.
+	 */
+	if (!bprm->file->f_op || !bprm->file->f_op->mmap)
+		return -ENOEXEC;
+
 	fd_offset = N_TXTOFF(ex);
 
 	/* Check initial limits. This avoids letting people circumvent
@@ -476,6 +483,13 @@
 		goto out;
 	}
 
+	/*
+	 * Requires a mmap handler. This prevents people from using a.out
+	 * as part of an exploit attack against /proc-related vulnerabilities.
+	 */
+	if (!file->f_op || !file->f_op->mmap)
+		goto out;
+
 	if (N_FLAGS(ex))
 		goto out;
 
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index dfd8cfb..6eb48e1 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1038,10 +1038,8 @@
 out_free_file:
 	sys_close(elf_exec_fileno);
 out_free_fh:
-	if (files) {
-		put_files_struct(current->files);
-		current->files = files;
-	}
+	if (files)
+		reset_files_struct(current, files);
 out_free_ph:
 	kfree(elf_phdata);
 	goto out;
@@ -1481,20 +1479,19 @@
 
 	if (signr) {
 		struct elf_thread_status *tmp;
-		read_lock(&tasklist_lock);
+		rcu_read_lock();
 		do_each_thread(g,p)
 			if (current->mm == p->mm && current != p) {
 				tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
 				if (!tmp) {
-					read_unlock(&tasklist_lock);
+					rcu_read_unlock();
 					goto cleanup;
 				}
-				INIT_LIST_HEAD(&tmp->list);
 				tmp->thread = p;
 				list_add(&tmp->list, &thread_list);
 			}
 		while_each_thread(g,p);
-		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 		list_for_each(t, &thread_list) {
 			struct elf_thread_status *tmp;
 			int sz;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 2f33658..f86d5c9 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1597,20 +1597,19 @@
 
 	if (signr) {
 		struct elf_thread_status *tmp;
-		read_lock(&tasklist_lock);
+		rcu_read_lock();
 		do_each_thread(g,p)
 			if (current->mm == p->mm && current != p) {
 				tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
 				if (!tmp) {
-					read_unlock(&tasklist_lock);
+					rcu_read_unlock();
 					goto cleanup;
 				}
-				INIT_LIST_HEAD(&tmp->list);
 				tmp->thread = p;
 				list_add(&tmp->list, &thread_list);
 			}
 		while_each_thread(g,p);
-		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 		list_for_each(t, &thread_list) {
 			struct elf_thread_status *tmp;
 			int sz;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 66ba137..1713c48 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -215,10 +215,8 @@
 	bprm->interp_flags = 0;
 	bprm->interp_data = 0;
 _unshare:
-	if (files) {
-		put_files_struct(current->files);
-		current->files = files;
-	}
+	if (files)
+		reset_files_struct(current, files);
 	goto _ret;
 }
 
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 045f988..4346468 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -543,11 +543,11 @@
 		return kobject_get(bdev->bd_disk->holder_dir);
 }
 
-static void add_symlink(struct kobject *from, struct kobject *to)
+static int add_symlink(struct kobject *from, struct kobject *to)
 {
 	if (!from || !to)
-		return;
-	sysfs_create_link(from, to, kobject_name(to));
+		return 0;
+	return sysfs_create_link(from, to, kobject_name(to));
 }
 
 static void del_symlink(struct kobject *from, struct kobject *to)
@@ -648,30 +648,38 @@
  * If there is no matching entry with @bo in @bdev->bd_holder_list,
  * add @bo to the list, create symlinks.
  *
- * Returns 1 if @bo was added to the list.
- * Returns 0 if @bo wasn't used by any reason and should be freed.
+ * Returns 0 if symlinks are created or already there.
+ * Returns -ve if something fails and @bo can be freed.
  */
 static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
 {
 	struct bd_holder *tmp;
+	int ret;
 
 	if (!bo)
-		return 0;
+		return -EINVAL;
 
 	list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
 		if (tmp->sdir == bo->sdir) {
 			tmp->count++;
+			/* We've already done what we need to do here. */
+			free_bd_holder(bo);
 			return 0;
 		}
 	}
 
 	if (!bd_holder_grab_dirs(bdev, bo))
-		return 0;
+		return -EBUSY;
 
-	add_symlink(bo->sdir, bo->sdev);
-	add_symlink(bo->hdir, bo->hdev);
-	list_add_tail(&bo->list, &bdev->bd_holder_list);
-	return 1;
+	ret = add_symlink(bo->sdir, bo->sdev);
+	if (ret == 0) {
+		ret = add_symlink(bo->hdir, bo->hdev);
+		if (ret)
+			del_symlink(bo->sdir, bo->sdev);
+	}
+	if (ret == 0)
+		list_add_tail(&bo->list, &bdev->bd_holder_list);
+	return ret;
 }
 
 /**
@@ -741,7 +749,9 @@
 
 	mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
 	res = bd_claim(bdev, holder);
-	if (res || !add_bd_holder(bdev, bo))
+	if (res == 0)
+		res = add_bd_holder(bdev, bo);
+	if (res)
 		free_bd_holder(bo);
 	mutex_unlock(&bdev->bd_mutex);
 
@@ -1021,7 +1031,7 @@
 				rescan_partitions(bdev->bd_disk, bdev);
 		} else {
 			mutex_lock_nested(&bdev->bd_contains->bd_mutex,
-					  BD_MUTEX_PARTITION);
+					  BD_MUTEX_WHOLE);
 			bdev->bd_contains->bd_part_count++;
 			mutex_unlock(&bdev->bd_contains->bd_mutex);
 		}
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 0009346..1f3285a 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -128,13 +128,31 @@
 
 	for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
 		if ((*cp)->major > major ||
-		    ((*cp)->major == major && (*cp)->baseminor >= baseminor))
+		    ((*cp)->major == major &&
+		     (((*cp)->baseminor >= baseminor) ||
+		      ((*cp)->baseminor + (*cp)->minorct > baseminor))))
 			break;
-	if (*cp && (*cp)->major == major &&
-	    (*cp)->baseminor < baseminor + minorct) {
-		ret = -EBUSY;
-		goto out;
+
+	/* Check for overlapping minor ranges.  */
+	if (*cp && (*cp)->major == major) {
+		int old_min = (*cp)->baseminor;
+		int old_max = (*cp)->baseminor + (*cp)->minorct - 1;
+		int new_min = baseminor;
+		int new_max = baseminor + minorct - 1;
+
+		/* New driver overlaps from the left.  */
+		if (new_max >= old_min && new_max <= old_max) {
+			ret = -EBUSY;
+			goto out;
+		}
+
+		/* New driver overlaps from the right.  */
+		if (new_min <= old_max && new_min >= old_min) {
+			ret = -EBUSY;
+			goto out;
+		}
 	}
+
 	cd->next = *cp;
 	*cp = cd;
 	mutex_unlock(&chrdevs_lock);
@@ -165,6 +183,15 @@
 	return cd;
 }
 
+/**
+ * register_chrdev_region() - register a range of device numbers
+ * @from: the first in the desired range of device numbers; must include
+ *        the major number.
+ * @count: the number of consecutive device numbers required
+ * @name: the name of the device or driver.
+ *
+ * Return value is zero on success, a negative error code on failure.
+ */
 int register_chrdev_region(dev_t from, unsigned count, const char *name)
 {
 	struct char_device_struct *cd;
@@ -190,6 +217,17 @@
 	return PTR_ERR(cd);
 }
 
+/**
+ * alloc_chrdev_region() - register a range of char device numbers
+ * @dev: output parameter for first assigned number
+ * @baseminor: first of the requested range of minor numbers
+ * @count: the number of minor numbers required
+ * @name: the name of the associated device or driver
+ *
+ * Allocates a range of char device numbers.  The major number will be
+ * chosen dynamically, and returned (along with the first minor number)
+ * in @dev.  Returns zero or a negative error code.
+ */
 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
 			const char *name)
 {
@@ -259,6 +297,15 @@
 	return err;
 }
 
+/**
+ * unregister_chrdev_region() - return a range of device numbers
+ * @from: the first in the range of numbers to unregister
+ * @count: the number of device numbers to unregister
+ *
+ * This function will unregister a range of @count device numbers,
+ * starting with @from.  The caller should normally be the one who
+ * allocated those numbers in the first place...
+ */
 void unregister_chrdev_region(dev_t from, unsigned count)
 {
 	dev_t to = from + count;
@@ -396,6 +443,16 @@
 	return cdev_get(p) ? 0 : -1;
 }
 
+/**
+ * cdev_add() - add a char device to the system
+ * @p: the cdev structure for the device
+ * @dev: the first device number for which this device is responsible
+ * @count: the number of consecutive minor numbers corresponding to this
+ *         device
+ *
+ * cdev_add() adds the device represented by @p to the system, making it
+ * live immediately.  A negative error code is returned on failure.
+ */
 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 {
 	p->dev = dev;
@@ -408,6 +465,13 @@
 	kobj_unmap(cdev_map, dev, count);
 }
 
+/**
+ * cdev_del() - remove a cdev from the system
+ * @p: the cdev structure to be removed
+ *
+ * cdev_del() removes @p from the system, possibly freeing the structure
+ * itself.
+ */
 void cdev_del(struct cdev *p)
 {
 	cdev_unmap(p->dev, p->count);
@@ -436,6 +500,11 @@
 	.release	= cdev_dynamic_release,
 };
 
+/**
+ * cdev_alloc() - allocate a cdev structure
+ *
+ * Allocates and returns a cdev structure, or NULL on failure.
+ */
 struct cdev *cdev_alloc(void)
 {
 	struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
@@ -447,6 +516,14 @@
 	return p;
 }
 
+/**
+ * cdev_init() - initialize a cdev structure
+ * @cdev: the structure to initialize
+ * @fops: the file_operations for this device
+ *
+ * Initializes @cdev, remembering @fops, making it ready to add to the
+ * system with cdev_add().
+ */
 void cdev_init(struct cdev *cdev, const struct file_operations *fops)
 {
 	memset(cdev, 0, sizeof *cdev);
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index ad96b69..a624c3e 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -543,8 +543,15 @@
 
 static int __init init_cramfs_fs(void)
 {
-	cramfs_uncompress_init();
-	return register_filesystem(&cramfs_fs_type);
+	int rv;
+
+	rv = cramfs_uncompress_init();
+	if (rv < 0)
+		return rv;
+	rv = register_filesystem(&cramfs_fs_type);
+	if (rv < 0)
+		cramfs_uncompress_exit();
+	return rv;
 }
 
 static void __exit exit_cramfs_fs(void)
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c
index 8def89f..fc3ccb7 100644
--- a/fs/cramfs/uncompress.c
+++ b/fs/cramfs/uncompress.c
@@ -68,11 +68,10 @@
 	return 0;
 }
 
-int cramfs_uncompress_exit(void)
+void cramfs_uncompress_exit(void)
 {
 	if (!--initialized) {
 		zlib_inflateEnd(&stream);
 		vfree(stream.workspace);
 	}
-	return 0;
 }
diff --git a/fs/dquot.c b/fs/dquot.c
index 0122a27..9af7895 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -834,6 +834,9 @@
 	if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
 		return;
 
+	mutex_lock(&tty_mutex);
+	if (!current->signal->tty)
+		goto out_lock;
 	tty_write_message(current->signal->tty, dquot->dq_sb->s_id);
 	if (warntype == ISOFTWARN || warntype == BSOFTWARN)
 		tty_write_message(current->signal->tty, ": warning, ");
@@ -861,6 +864,8 @@
 			break;
 	}
 	tty_write_message(current->signal->tty, msg);
+out_lock:
+	mutex_unlock(&tty_mutex);
 }
 
 static inline void flush_warnings(struct dquot **dquots, char *warntype)
diff --git a/fs/exec.c b/fs/exec.c
index 97df6e0..a8efe35 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -898,8 +898,7 @@
 	return 0;
 
 mmap_failed:
-	put_files_struct(current->files);
-	current->files = files;
+	reset_files_struct(current, files);
 out:
 	return retval;
 }
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 1ee2523..d50fc47 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/blkdev.h>
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg)
@@ -112,6 +113,16 @@
 	}
 }
 
+static int fat_file_release(struct inode *inode, struct file *filp)
+{
+	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);
+	}
+	return 0;
+}
+
 const struct file_operations fat_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
@@ -121,6 +132,7 @@
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
+	.release	= fat_file_release,
 	.ioctl		= fat_generic_ioctl,
 	.fsync		= file_fsync,
 	.sendfile	= generic_file_sendfile,
@@ -289,6 +301,7 @@
 	lock_kernel();
 	fat_free(inode, nr_clusters);
 	unlock_kernel();
+	fat_flush_inodes(inode->i_sb, inode, NULL);
 }
 
 struct inode_operations fat_file_inode_operations = {
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index ab96ae8..0457380 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -24,6 +24,7 @@
 #include <linux/vfs.h>
 #include <linux/parser.h>
 #include <linux/uio.h>
+#include <linux/writeback.h>
 #include <asm/unaligned.h>
 
 #ifndef CONFIG_FAT_DEFAULT_IOCHARSET
@@ -853,7 +854,7 @@
 	Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
 	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
 	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
-	Opt_obsolate, Opt_err,
+	Opt_obsolate, Opt_flush, Opt_err,
 };
 
 static match_table_t fat_tokens = {
@@ -885,7 +886,8 @@
 	{Opt_obsolate, "cvf_format=%20s"},
 	{Opt_obsolate, "cvf_options=%100s"},
 	{Opt_obsolate, "posix"},
-	{Opt_err, NULL}
+	{Opt_flush, "flush"},
+	{Opt_err, NULL},
 };
 static match_table_t msdos_tokens = {
 	{Opt_nodots, "nodots"},
@@ -1026,6 +1028,9 @@
 				return 0;
 			opts->codepage = option;
 			break;
+		case Opt_flush:
+			opts->flush = 1;
+			break;
 
 		/* msdos specific */
 		case Opt_dots:
@@ -1425,6 +1430,56 @@
 
 EXPORT_SYMBOL_GPL(fat_fill_super);
 
+/*
+ * helper function for fat_flush_inodes.  This writes both the inode
+ * and the file data blocks, waiting for in flight data blocks before
+ * the start of the call.  It does not wait for any io started
+ * during the call
+ */
+static int writeback_inode(struct inode *inode)
+{
+
+	int ret;
+	struct address_space *mapping = inode->i_mapping;
+	struct writeback_control wbc = {
+	       .sync_mode = WB_SYNC_NONE,
+	      .nr_to_write = 0,
+	};
+	/* if we used WB_SYNC_ALL, sync_inode waits for the io for the
+	* inode to finish.  So WB_SYNC_NONE is sent down to sync_inode
+	* and filemap_fdatawrite is used for the data blocks
+	*/
+	ret = sync_inode(inode, &wbc);
+	if (!ret)
+	       ret = filemap_fdatawrite(mapping);
+	return ret;
+}
+
+/*
+ * write data and metadata corresponding to i1 and i2.  The io is
+ * started but we do not wait for any of it to finish.
+ *
+ * filemap_flush is used for the block device, so if there is a dirty
+ * page for a block already in flight, we will not wait and start the
+ * io over again
+ */
+int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2)
+{
+	int ret = 0;
+	if (!MSDOS_SB(sb)->options.flush)
+		return 0;
+	if (i1)
+		ret = writeback_inode(i1);
+	if (!ret && i2)
+		ret = writeback_inode(i2);
+	if (!ret && sb) {
+		struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
+		ret = filemap_flush(mapping);
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fat_flush_inodes);
+
 static int __init init_fat_fs(void)
 {
 	int err;
diff --git a/fs/file.c b/fs/file.c
index 8d3bfca..8e81775 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -288,71 +288,63 @@
 }
 
 /*
- * Expands the file descriptor table - it will allocate a new fdtable and
- * both fd array and fdset. It is expected to be called with the
- * files_lock held.
+ * Expand the file descriptor table.
+ * This function will allocate a new fdtable and both fd array and fdset, of
+ * the given size.
+ * Return <0 error code on error; 1 on successful completion.
+ * The files->file_lock should be held on entry, and will be held on exit.
  */
 static int expand_fdtable(struct files_struct *files, int nr)
 	__releases(files->file_lock)
 	__acquires(files->file_lock)
 {
-	int error = 0;
-	struct fdtable *fdt;
-	struct fdtable *nfdt = NULL;
+	struct fdtable *new_fdt, *cur_fdt;
 
 	spin_unlock(&files->file_lock);
-	nfdt = alloc_fdtable(nr);
-	if (!nfdt) {
-		error = -ENOMEM;
-		spin_lock(&files->file_lock);
-		goto out;
-	}
-
+	new_fdt = alloc_fdtable(nr);
 	spin_lock(&files->file_lock);
-	fdt = files_fdtable(files);
+	if (!new_fdt)
+		return -ENOMEM;
 	/*
-	 * Check again since another task may have expanded the
-	 * fd table while we dropped the lock
+	 * Check again since another task may have expanded the fd table while
+	 * we dropped the lock
 	 */
-	if (nr >= fdt->max_fds || nr >= fdt->max_fdset) {
-		copy_fdtable(nfdt, fdt);
+	cur_fdt = files_fdtable(files);
+	if (nr >= cur_fdt->max_fds || nr >= cur_fdt->max_fdset) {
+		/* Continue as planned */
+		copy_fdtable(new_fdt, cur_fdt);
+		rcu_assign_pointer(files->fdt, new_fdt);
+		free_fdtable(cur_fdt);
 	} else {
-		/* Somebody expanded while we dropped file_lock */
-		spin_unlock(&files->file_lock);
-		__free_fdtable(nfdt);
-		spin_lock(&files->file_lock);
-		goto out;
+		/* Somebody else expanded, so undo our attempt */
+		__free_fdtable(new_fdt);
 	}
-	rcu_assign_pointer(files->fdt, nfdt);
-	free_fdtable(fdt);
-out:
-	return error;
+	return 1;
 }
 
 /*
  * Expand files.
- * Return <0 on error; 0 nothing done; 1 files expanded, we may have blocked.
- * Should be called with the files->file_lock spinlock held for write.
+ * This function will expand the file structures, if the requested size exceeds
+ * the current capacity and there is room for expansion.
+ * Return <0 error code on error; 0 when nothing done; 1 when files were
+ * expanded and execution may have blocked.
+ * The files->file_lock should be held on entry, and will be held on exit.
  */
 int expand_files(struct files_struct *files, int nr)
 {
-	int err, expand = 0;
 	struct fdtable *fdt;
 
 	fdt = files_fdtable(files);
-	if (nr >= fdt->max_fdset || nr >= fdt->max_fds) {
-		if (fdt->max_fdset >= NR_OPEN ||
-			fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) {
-			err = -EMFILE;
-			goto out;
-		}
-		expand = 1;
-		if ((err = expand_fdtable(files, nr)))
-			goto out;
-	}
-	err = expand;
-out:
-	return err;
+	/* Do we need to expand? */
+	if (nr < fdt->max_fdset && nr < fdt->max_fds)
+		return 0;
+	/* Can we expand? */
+	if (fdt->max_fdset >= NR_OPEN || fdt->max_fds >= NR_OPEN ||
+	    nr >= NR_OPEN)
+		return -EMFILE;
+
+	/* All good, so we try */
+	return expand_fdtable(files, nr);
 }
 
 static void __devinit fdtable_defer_list_init(int cpu)
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 9f10728..e3fa77c 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -69,8 +69,6 @@
 	int res = 0;
 	struct file_system_type ** p;
 
-	if (!fs)
-		return -EINVAL;
 	if (fs->next)
 		return -EBUSY;
 	INIT_LIST_HEAD(&fs->fs_supers);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index b74b791..ac28b08 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -260,12 +260,17 @@
 static int __init
 vxfs_init(void)
 {
+	int rv;
+
 	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
 			sizeof(struct vxfs_inode_info), 0, 
 			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL, NULL);
-	if (vxfs_inode_cachep)
-		return register_filesystem(&vxfs_fs_type);
-	return -ENOMEM;
+	if (!vxfs_inode_cachep)
+		return -ENOMEM;
+	rv = register_filesystem(&vxfs_fs_type);
+	if (rv < 0)
+		kmem_cache_destroy(vxfs_inode_cachep);
+	return rv;
 }
 
 static void __exit
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 1e2006c..4fc557c 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -212,6 +212,7 @@
  * Called with fc->lock, unlocks it
  */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
+	__releases(fc->lock)
 {
 	void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
 	req->end = NULL;
@@ -640,6 +641,7 @@
  */
 static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req,
 			       const struct iovec *iov, unsigned long nr_segs)
+	__releases(fc->lock)
 {
 	struct fuse_copy_state cs;
 	struct fuse_in_header ih;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 409ce6a..f85b2a2 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -776,7 +776,7 @@
 		if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
 			return -EACCES;
 
-		if (nd && (nd->flags & LOOKUP_ACCESS))
+		if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR)))
 			return fuse_access(inode, mask);
 		return 0;
 	}
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index cb7cadb..7d0a9ae 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -251,6 +251,7 @@
 	memset(&outarg, 0, sizeof(outarg));
 	req->in.numargs = 0;
 	req->in.h.opcode = FUSE_STATFS;
+	req->in.h.nodeid = get_node_id(dentry->d_inode);
 	req->out.numargs = 1;
 	req->out.args[0].size =
 		fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg);
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
new file mode 100644
index 0000000..9ccb789
--- /dev/null
+++ b/fs/generic_acl.c
@@ -0,0 +1,197 @@
+/*
+ * fs/generic_acl.c
+ *
+ * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/generic_acl.h>
+
+/**
+ * generic_acl_list  -  Generic xattr_handler->list() operation
+ * @ops:	Filesystem specific getacl and setacl callbacks
+ */
+size_t
+generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
+		 int type, char *list, size_t list_size)
+{
+	struct posix_acl *acl;
+	const char *name;
+	size_t size;
+
+	acl = ops->getacl(inode, type);
+	if (!acl)
+		return 0;
+	posix_acl_release(acl);
+
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			name = POSIX_ACL_XATTR_ACCESS;
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			name = POSIX_ACL_XATTR_DEFAULT;
+			break;
+
+		default:
+			return 0;
+	}
+	size = strlen(name) + 1;
+	if (list && size <= list_size)
+		memcpy(list, name, size);
+	return size;
+}
+
+/**
+ * generic_acl_get  -  Generic xattr_handler->get() operation
+ * @ops:	Filesystem specific getacl and setacl callbacks
+ */
+int
+generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
+		int type, void *buffer, size_t size)
+{
+	struct posix_acl *acl;
+	int error;
+
+	acl = ops->getacl(inode, type);
+	if (!acl)
+		return -ENODATA;
+	error = posix_acl_to_xattr(acl, buffer, size);
+	posix_acl_release(acl);
+
+	return error;
+}
+
+/**
+ * generic_acl_set  -  Generic xattr_handler->set() operation
+ * @ops:	Filesystem specific getacl and setacl callbacks
+ */
+int
+generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
+		int type, const void *value, size_t size)
+{
+	struct posix_acl *acl = NULL;
+	int error;
+
+	if (S_ISLNK(inode->i_mode))
+		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);
+	}
+	if (acl) {
+		mode_t mode;
+
+		error = posix_acl_valid(acl);
+		if (error)
+			goto failed;
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				mode = inode->i_mode;
+				error = posix_acl_equiv_mode(acl, &mode);
+				if (error < 0)
+					goto failed;
+				inode->i_mode = mode;
+				if (error == 0) {
+					posix_acl_release(acl);
+					acl = NULL;
+				}
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				if (!S_ISDIR(inode->i_mode)) {
+					error = -EINVAL;
+					goto failed;
+				}
+				break;
+		}
+	}
+	ops->setacl(inode, type, acl);
+	error = 0;
+failed:
+	posix_acl_release(acl);
+	return error;
+}
+
+/**
+ * generic_acl_init  -  Take care of acl inheritance at @inode create time
+ * @ops:	Filesystem specific getacl and setacl callbacks
+ *
+ * Files created inside a directory with a default ACL inherit the
+ * directory's default ACL.
+ */
+int
+generic_acl_init(struct inode *inode, struct inode *dir,
+		 struct generic_acl_operations *ops)
+{
+	struct posix_acl *acl = NULL;
+	mode_t mode = inode->i_mode;
+	int error;
+
+	inode->i_mode = mode & ~current->fs->umask;
+	if (!S_ISLNK(inode->i_mode))
+		acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
+	if (acl) {
+		struct posix_acl *clone;
+
+		if (S_ISDIR(inode->i_mode)) {
+			clone = posix_acl_clone(acl, GFP_KERNEL);
+			error = -ENOMEM;
+			if (!clone)
+				goto cleanup;
+			ops->setacl(inode, ACL_TYPE_DEFAULT, clone);
+			posix_acl_release(clone);
+		}
+		clone = posix_acl_clone(acl, GFP_KERNEL);
+		error = -ENOMEM;
+		if (!clone)
+			goto cleanup;
+		error = posix_acl_create_masq(clone, &mode);
+		if (error >= 0) {
+			inode->i_mode = mode;
+			if (error > 0)
+				ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+		}
+		posix_acl_release(clone);
+	}
+	error = 0;
+
+cleanup:
+	posix_acl_release(acl);
+	return error;
+}
+
+/**
+ * generic_acl_chmod  -  change the access acl of @inode upon chmod()
+ * @ops:	FIlesystem specific getacl and setacl callbacks
+ *
+ * A chmod also changes the permissions of the owner, group/mask, and
+ * other ACL entries.
+ */
+int
+generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
+{
+	struct posix_acl *acl, *clone;
+	int error = 0;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+	acl = ops->getacl(inode, ACL_TYPE_ACCESS);
+	if (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)
+			ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+		posix_acl_release(clone);
+	}
+	return error;
+}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e025a31..f5b8f32 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -229,7 +229,7 @@
 	clear_inode(inode);
 }
 
-static void hugetlbfs_forget_inode(struct inode *inode)
+static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock)
 {
 	struct super_block *sb = inode->i_sb;
 
diff --git a/fs/inode.c b/fs/inode.c
index f5c04dd..abf7747 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -133,7 +133,6 @@
 		inode->i_bdev = NULL;
 		inode->i_cdev = NULL;
 		inode->i_rdev = 0;
-		inode->i_security = NULL;
 		inode->dirtied_when = 0;
 		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 4527692..c34b862 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -960,30 +960,30 @@
 			goto abort;
 		}
 		
-		if (nextblk) {
-			while (b_off >= (offset + sect_size)) {
-				struct inode *ninode;
-				
-				offset += sect_size;
-				if (nextblk == 0)
-					goto abort;
-				ninode = isofs_iget(inode->i_sb, nextblk, nextoff);
-				if (!ninode)
-					goto abort;
-				firstext  = ISOFS_I(ninode)->i_first_extent;
-				sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode);
-				nextblk   = ISOFS_I(ninode)->i_next_section_block;
-				nextoff   = ISOFS_I(ninode)->i_next_section_offset;
-				iput(ninode);
-				
-				if (++section > 100) {
-					printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
-					printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
-					       "nextblk=%lu nextoff=%lu\n",
-					       iblock, firstext, (unsigned) sect_size,
-					       nextblk, nextoff);
-					goto abort;
-				}
+		/* On the last section, nextblk == 0, section size is likely to
+		 * exceed sect_size by a partial block, and access beyond the
+		 * end of the file will reach beyond the section size, too.
+		 */
+		while (nextblk && (b_off >= (offset + sect_size))) {
+			struct inode *ninode;
+
+			offset += sect_size;
+			ninode = isofs_iget(inode->i_sb, nextblk, nextoff);
+			if (!ninode)
+				goto abort;
+			firstext  = ISOFS_I(ninode)->i_first_extent;
+			sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode);
+			nextblk   = ISOFS_I(ninode)->i_next_section_block;
+			nextoff   = ISOFS_I(ninode)->i_next_section_offset;
+			iput(ninode);
+
+			if (++section > 100) {
+				printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
+				printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
+				       "nextblk=%lu nextoff=%lu\n",
+				       iblock, firstext, (unsigned) sect_size,
+				       nextblk, nextoff);
+				goto abort;
 			}
 		}
 		
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 2fc66c3..7af6099 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -715,18 +715,8 @@
 	if (!journal)
 		return NULL;
 
-	journal->j_dev = bdev;
-	journal->j_fs_dev = fs_dev;
-	journal->j_blk_offset = start;
-	journal->j_maxlen = len;
-	journal->j_blocksize = blocksize;
-
-	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;
-
 	/* 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);
@@ -736,6 +726,15 @@
 		kfree(journal);
 		journal = NULL;
 	}
+	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;
 
 	return journal;
 }
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index 445eed6..11563fe 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -46,7 +46,7 @@
 #ifdef __KERNEL__
 
 /* Release readahead buffers after use */
-void journal_brelse_array(struct buffer_head *b[], int n)
+static void journal_brelse_array(struct buffer_head *b[], int n)
 {
 	while (--n >= 0)
 		brelse (b[n]);
diff --git a/fs/libfs.c b/fs/libfs.c
index 8db5afb..3793aaa 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -317,17 +317,9 @@
 
 int simple_readpage(struct file *file, struct page *page)
 {
-	void *kaddr;
-
-	if (PageUptodate(page))
-		goto out;
-
-	kaddr = kmap_atomic(page, KM_USER0);
-	memset(kaddr, 0, PAGE_CACHE_SIZE);
-	kunmap_atomic(kaddr, KM_USER0);
+	clear_highpage(page);
 	flush_dcache_page(page);
 	SetPageUptodate(page);
-out:
 	unlock_page(page);
 	return 0;
 }
diff --git a/fs/mbcache.c b/fs/mbcache.c
index e4fde1a..0ff7125 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -160,6 +160,7 @@
 
 static void
 __mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
+	__releases(mb_cache_spinlock)
 {
 	/* Wake up all processes queuing for this cache entry. */
 	if (ce->e_queued)
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 9e44158..d220165 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -280,7 +280,7 @@
 			struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
-	struct inode *inode;
+	struct inode *inode = NULL;
 	struct fat_slot_info sinfo;
 	struct timespec ts;
 	unsigned char msdos_name[MSDOS_NAME];
@@ -316,6 +316,8 @@
 	d_instantiate(dentry, inode);
 out:
 	unlock_kernel();
+	if (!err)
+		err = fat_flush_inodes(sb, dir, inode);
 	return err;
 }
 
@@ -348,6 +350,8 @@
 	fat_detach(inode);
 out:
 	unlock_kernel();
+	if (!err)
+		err = fat_flush_inodes(inode->i_sb, dir, inode);
 
 	return err;
 }
@@ -401,6 +405,7 @@
 	d_instantiate(dentry, inode);
 
 	unlock_kernel();
+	fat_flush_inodes(sb, dir, inode);
 	return 0;
 
 out_free:
@@ -430,6 +435,8 @@
 	fat_detach(inode);
 out:
 	unlock_kernel();
+	if (!err)
+		err = fat_flush_inodes(inode->i_sb, dir, inode);
 
 	return err;
 }
@@ -635,6 +642,8 @@
 			      new_dir, new_msdos_name, new_dentry, is_hid);
 out:
 	unlock_kernel();
+	if (!err)
+		err = fat_flush_inodes(old_dir->i_sb, old_dir, new_dir);
 	return err;
 }
 
diff --git a/fs/namei.c b/fs/namei.c
index 808e4ea..2892e68 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -518,18 +518,20 @@
 static __always_inline int
 walk_init_root(const char *name, struct nameidata *nd)
 {
-	read_lock(&current->fs->lock);
-	if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
-		nd->mnt = mntget(current->fs->altrootmnt);
-		nd->dentry = dget(current->fs->altroot);
-		read_unlock(&current->fs->lock);
+	struct fs_struct *fs = current->fs;
+
+	read_lock(&fs->lock);
+	if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
+		nd->mnt = mntget(fs->altrootmnt);
+		nd->dentry = dget(fs->altroot);
+		read_unlock(&fs->lock);
 		if (__emul_lookup_dentry(name,nd))
 			return 0;
-		read_lock(&current->fs->lock);
+		read_lock(&fs->lock);
 	}
-	nd->mnt = mntget(current->fs->rootmnt);
-	nd->dentry = dget(current->fs->root);
-	read_unlock(&current->fs->lock);
+	nd->mnt = mntget(fs->rootmnt);
+	nd->dentry = dget(fs->root);
+	read_unlock(&fs->lock);
 	return 1;
 }
 
@@ -724,17 +726,19 @@
 
 static __always_inline void follow_dotdot(struct nameidata *nd)
 {
+	struct fs_struct *fs = current->fs;
+
 	while(1) {
 		struct vfsmount *parent;
 		struct dentry *old = nd->dentry;
 
-                read_lock(&current->fs->lock);
-		if (nd->dentry == current->fs->root &&
-		    nd->mnt == current->fs->rootmnt) {
-                        read_unlock(&current->fs->lock);
+                read_lock(&fs->lock);
+		if (nd->dentry == fs->root &&
+		    nd->mnt == fs->rootmnt) {
+                        read_unlock(&fs->lock);
 			break;
 		}
-                read_unlock(&current->fs->lock);
+                read_unlock(&fs->lock);
 		spin_lock(&dcache_lock);
 		if (nd->dentry != nd->mnt->mnt_root) {
 			nd->dentry = dget(nd->dentry->d_parent);
@@ -1042,15 +1046,17 @@
 		struct vfsmount *old_mnt = nd->mnt;
 		struct qstr last = nd->last;
 		int last_type = nd->last_type;
+		struct fs_struct *fs = current->fs;
+
 		/*
-		 * NAME was not found in alternate root or it's a directory.  Try to find
-		 * it in the normal root:
+		 * NAME was not found in alternate root or it's a directory.
+		 * Try to find it in the normal root:
 		 */
 		nd->last_type = LAST_ROOT;
-		read_lock(&current->fs->lock);
-		nd->mnt = mntget(current->fs->rootmnt);
-		nd->dentry = dget(current->fs->root);
-		read_unlock(&current->fs->lock);
+		read_lock(&fs->lock);
+		nd->mnt = mntget(fs->rootmnt);
+		nd->dentry = dget(fs->root);
+		read_unlock(&fs->lock);
 		if (path_walk(name, nd) == 0) {
 			if (nd->dentry->d_inode) {
 				dput(old_dentry);
@@ -1074,6 +1080,7 @@
 	struct vfsmount *mnt = NULL, *oldmnt;
 	struct dentry *dentry = NULL, *olddentry;
 	int err;
+	struct fs_struct *fs = current->fs;
 
 	if (!emul)
 		goto set_it;
@@ -1083,12 +1090,12 @@
 		dentry = nd.dentry;
 	}
 set_it:
-	write_lock(&current->fs->lock);
-	oldmnt = current->fs->altrootmnt;
-	olddentry = current->fs->altroot;
-	current->fs->altrootmnt = mnt;
-	current->fs->altroot = dentry;
-	write_unlock(&current->fs->lock);
+	write_lock(&fs->lock);
+	oldmnt = fs->altrootmnt;
+	olddentry = fs->altroot;
+	fs->altrootmnt = mnt;
+	fs->altroot = dentry;
+	write_unlock(&fs->lock);
 	if (olddentry) {
 		dput(olddentry);
 		mntput(oldmnt);
@@ -1102,29 +1109,30 @@
 	int retval = 0;
 	int fput_needed;
 	struct file *file;
+	struct fs_struct *fs = current->fs;
 
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
 	nd->flags = flags;
 	nd->depth = 0;
 
 	if (*name=='/') {
-		read_lock(&current->fs->lock);
-		if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
-			nd->mnt = mntget(current->fs->altrootmnt);
-			nd->dentry = dget(current->fs->altroot);
-			read_unlock(&current->fs->lock);
+		read_lock(&fs->lock);
+		if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
+			nd->mnt = mntget(fs->altrootmnt);
+			nd->dentry = dget(fs->altroot);
+			read_unlock(&fs->lock);
 			if (__emul_lookup_dentry(name,nd))
 				goto out; /* found in altroot */
-			read_lock(&current->fs->lock);
+			read_lock(&fs->lock);
 		}
-		nd->mnt = mntget(current->fs->rootmnt);
-		nd->dentry = dget(current->fs->root);
-		read_unlock(&current->fs->lock);
+		nd->mnt = mntget(fs->rootmnt);
+		nd->dentry = dget(fs->root);
+		read_unlock(&fs->lock);
 	} else if (dfd == AT_FDCWD) {
-		read_lock(&current->fs->lock);
-		nd->mnt = mntget(current->fs->pwdmnt);
-		nd->dentry = dget(current->fs->pwd);
-		read_unlock(&current->fs->lock);
+		read_lock(&fs->lock);
+		nd->mnt = mntget(fs->pwdmnt);
+		nd->dentry = dget(fs->pwd);
+		read_unlock(&fs->lock);
 	} else {
 		struct dentry *dentry;
 
diff --git a/fs/namespace.c b/fs/namespace.c
index 36d1808..6ede3a5 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/quotaops.h>
 #include <linux/acct.h>
 #include <linux/capability.h>
@@ -1813,6 +1814,7 @@
 	struct list_head *d;
 	unsigned int nr_hash;
 	int i;
+	int err;
 
 	init_rwsem(&namespace_sem);
 
@@ -1853,8 +1855,14 @@
 		d++;
 		i--;
 	} while (i);
-	sysfs_init();
-	subsystem_register(&fs_subsys);
+	err = sysfs_init();
+	if (err)
+		printk(KERN_WARNING "%s: sysfs_init error: %d\n",
+			__FUNCTION__, err);
+	err = subsystem_register(&fs_subsys);
+	if (err)
+		printk(KERN_WARNING "%s: subsystem_register error: %d\n",
+			__FUNCTION__, err);
 	init_rootfs();
 	init_mount_tree();
 }
diff --git a/fs/open.c b/fs/open.c
index 303f06d..304c1c7 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -546,7 +546,8 @@
 	struct nameidata nd;
 	int error;
 
-	error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
+	error = __user_walk(filename,
+			    LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd);
 	if (error)
 		goto out;
 
@@ -1172,6 +1173,7 @@
 	struct file * filp;
 	struct files_struct *files = current->files;
 	struct fdtable *fdt;
+	int retval;
 
 	spin_lock(&files->file_lock);
 	fdt = files_fdtable(files);
@@ -1184,7 +1186,16 @@
 	FD_CLR(fd, fdt->close_on_exec);
 	__put_unused_fd(files, fd);
 	spin_unlock(&files->file_lock);
-	return filp_close(filp, files);
+	retval = filp_close(filp, files);
+
+	/* can't restart close syscall because file table entry was cleared */
+	if (unlikely(retval == -ERESTARTSYS ||
+		     retval == -ERESTARTNOINTR ||
+		     retval == -ERESTARTNOHAND ||
+		     retval == -ERESTART_RESTARTBLOCK))
+		retval = -EINTR;
+
+	return retval;
 
 out_unlock:
 	spin_unlock(&files->file_lock);
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 8f12587..4f8df71 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -58,6 +58,31 @@
 	return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
 }
 
+/* Value is EBCDIC 'IBMA' */
+#define AIX_LABEL_MAGIC1	0xC9
+#define AIX_LABEL_MAGIC2	0xC2
+#define AIX_LABEL_MAGIC3	0xD4
+#define AIX_LABEL_MAGIC4	0xC1
+static int aix_magic_present(unsigned char *p, struct block_device *bdev)
+{
+	Sector sect;
+	unsigned char *d;
+	int ret = 0;
+
+	if (p[0] != AIX_LABEL_MAGIC1 &&
+		p[1] != AIX_LABEL_MAGIC2 &&
+		p[2] != AIX_LABEL_MAGIC3 &&
+		p[3] != AIX_LABEL_MAGIC4)
+		return 0;
+	d = read_dev_sector(bdev, 7, &sect);
+	if (d) {
+		if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
+			ret = 1;
+		put_dev_sector(sect);
+	};
+	return ret;
+}
+
 /*
  * Create devices for each logical partition in an extended partition.
  * The logical partitions form a linked list, with each entry being
@@ -393,6 +418,12 @@
 		return 0;
 	}
 
+	if (aix_magic_present(data, bdev)) {
+		put_dev_sector(sect);
+		printk( " [AIX]");
+		return 0;
+	}
+
 	/*
 	 * Now that the 55aa signature is present, this is probably
 	 * either the boot sector of a FAT filesystem or a DOS-type
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 0b615d6..c0e5549 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -347,6 +347,8 @@
 	sigemptyset(&sigign);
 	sigemptyset(&sigcatch);
 	cutime = cstime = utime = stime = cputime_zero;
+
+	mutex_lock(&tty_mutex);
 	read_lock(&tasklist_lock);
 	if (task->sighand) {
 		spin_lock_irq(&task->sighand->siglock);
@@ -388,6 +390,7 @@
 	}
 	ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
 	read_unlock(&tasklist_lock);
+	mutex_unlock(&tty_mutex);
 
 	if (!whole || num_threads<2)
 		wchan = get_wchan(task);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index fe8d55f..89c20d9 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -797,7 +797,7 @@
 static ssize_t mem_write(struct file * file, const char * buf,
 			 size_t count, loff_t *ppos)
 {
-	int copied = 0;
+	int copied;
 	char *page;
 	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
 	unsigned long dst = *ppos;
@@ -814,6 +814,7 @@
 	if (!page)
 		goto out;
 
+	copied = 0;
 	while (count > 0) {
 		int this_len, retval;
 
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 3ceff38..1294eda 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -100,7 +100,7 @@
 	int sz;
 
 	sz = sizeof(struct elf_note);
-	sz += roundup(strlen(en->name), 4);
+	sz += roundup((strlen(en->name) + 1), 4);
 	sz += roundup(en->datasz, 4);
 
 	return sz;
@@ -116,7 +116,7 @@
 
 #define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0)
 
-	en.n_namesz = strlen(men->name);
+	en.n_namesz = strlen(men->name) + 1;
 	en.n_descsz = men->datasz;
 	en.n_type = men->type;
 
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile
index 3a59309..0eb7ac0 100644
--- a/fs/reiserfs/Makefile
+++ b/fs/reiserfs/Makefile
@@ -28,7 +28,7 @@
 # will work around it. If any other architecture displays this behavior,
 # add it here.
 ifeq ($(CONFIG_PPC32),y)
-EXTRA_CFLAGS := -O1
+EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1)
 endif
 
 TAGS:
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 1627edd..1cfbe85 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -130,7 +130,7 @@
 	reiserfs_write_lock(p_s_inode->i_sb);
 	barrier_done = reiserfs_commit_for_inode(p_s_inode);
 	reiserfs_write_unlock(p_s_inode->i_sb);
-	if (barrier_done != 1)
+	if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb))
 		blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
 	if (barrier_done < 0)
 		return barrier_done;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 8810fda..7e5a2f5 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1127,9 +1127,9 @@
 	REISERFS_I(inode)->i_prealloc_count = 0;
 	REISERFS_I(inode)->i_trans_id = 0;
 	REISERFS_I(inode)->i_jl = NULL;
-	REISERFS_I(inode)->i_acl_access = NULL;
-	REISERFS_I(inode)->i_acl_default = NULL;
-	init_rwsem(&REISERFS_I(inode)->xattr_sem);
+	reiserfs_init_acl_access(inode);
+	reiserfs_init_acl_default(inode);
+	reiserfs_init_xattr_rwsem(inode);
 
 	if (stat_data_v1(ih)) {
 		struct stat_data_v1 *sd =
@@ -1834,9 +1834,9 @@
 	REISERFS_I(inode)->i_attrs =
 	    REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
 	sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
-	REISERFS_I(inode)->i_acl_access = NULL;
-	REISERFS_I(inode)->i_acl_default = NULL;
-	init_rwsem(&REISERFS_I(inode)->xattr_sem);
+	reiserfs_init_acl_access(inode);
+	reiserfs_init_acl_default(inode);
+	reiserfs_init_xattr_rwsem(inode);
 
 	if (old_format_only(sb))
 		make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET,
@@ -1974,11 +1974,13 @@
 	 * iput doesn't deadlock in reiserfs_delete_xattrs. The locking
 	 * code really needs to be reworked, but this will take care of it
 	 * for now. -jeffm */
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 	if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) {
 		reiserfs_write_unlock_xattrs(dir->i_sb);
 		iput(inode);
 		reiserfs_write_lock_xattrs(dir->i_sb);
 	} else
+#endif
 		iput(inode);
 	return err;
 }
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 9b3672d..e6b5ccf 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1186,6 +1186,21 @@
 	return NULL;
 }
 
+static int newer_jl_done(struct reiserfs_journal_cnode *cn)
+{
+	struct super_block *sb = cn->sb;
+	b_blocknr_t blocknr = cn->blocknr;
+
+	cn = cn->hprev;
+	while (cn) {
+		if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist &&
+		    atomic_read(&cn->jlist->j_commit_left) != 0)
+				    return 0;
+		cn = cn->hprev;
+	}
+	return 1;
+}
+
 static void remove_journal_hash(struct super_block *,
 				struct reiserfs_journal_cnode **,
 				struct reiserfs_journal_list *, unsigned long,
@@ -1604,6 +1619,31 @@
 	return err;
 }
 
+static int test_transaction(struct super_block *s,
+                            struct reiserfs_journal_list *jl)
+{
+	struct reiserfs_journal_cnode *cn;
+
+	if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0)
+		return 1;
+
+	cn = jl->j_realblock;
+	while (cn) {
+		/* if the blocknr == 0, this has been cleared from the hash,
+		 ** skip it
+		 */
+		if (cn->blocknr == 0) {
+			goto next;
+		}
+		if (cn->bh && !newer_jl_done(cn))
+			return 0;
+	      next:
+		cn = cn->next;
+		cond_resched();
+	}
+	return 0;
+}
+
 static int write_one_transaction(struct super_block *s,
 				 struct reiserfs_journal_list *jl,
 				 struct buffer_chunk *chunk)
@@ -3433,16 +3473,6 @@
 		flush_commit_list(p_s_sb, jl, 1);
 	}
 	unlock_kernel();
-	/*
-	 * this is a little racey, but there's no harm in missing
-	 * the filemap_fdata_write
-	 */
-	if (!atomic_read(&journal->j_async_throttle)
-	    && !reiserfs_is_journal_aborted(journal)) {
-		atomic_inc(&journal->j_async_throttle);
-		filemap_fdatawrite(p_s_sb->s_bdev->bd_inode->i_mapping);
-		atomic_dec(&journal->j_async_throttle);
-	}
 }
 
 /*
@@ -3844,7 +3874,9 @@
 		entry = journal->j_journal_list.next;
 		jl = JOURNAL_LIST_ENTRY(entry);
 		/* this check should always be run, to send old lists to disk */
-		if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4))) {
+		if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) &&
+		    atomic_read(&jl->j_commit_left) == 0 &&
+		    test_transaction(s, jl)) {
 			flush_used_journal_lists(s, jl);
 		} else {
 			break;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b40d4d6..80fc3b3 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -510,8 +510,10 @@
 	    SLAB_CTOR_CONSTRUCTOR) {
 		INIT_LIST_HEAD(&ei->i_prealloc_list);
 		inode_init_once(&ei->vfs_inode);
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 		ei->i_acl_access = NULL;
 		ei->i_acl_default = NULL;
+#endif
 	}
 }
 
@@ -560,6 +562,7 @@
 	reiserfs_write_unlock(inode->i_sb);
 }
 
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 static void reiserfs_clear_inode(struct inode *inode)
 {
 	struct posix_acl *acl;
@@ -574,6 +577,9 @@
 		posix_acl_release(acl);
 	REISERFS_I(inode)->i_acl_default = NULL;
 }
+#else
+#define reiserfs_clear_inode NULL
+#endif
 
 #ifdef CONFIG_QUOTA
 static ssize_t reiserfs_quota_write(struct super_block *, int, const char *,
diff --git a/fs/select.c b/fs/select.c
index 33b72ba..dcbc111 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -658,8 +658,6 @@
  	unsigned int i;
 	struct poll_list *head;
  	struct poll_list *walk;
-	struct fdtable *fdt;
-	int max_fdset;
 	/* Allocate small arguments on the stack to save memory and be
 	   faster - use long to make sure the buffer is aligned properly
 	   on 64 bit archs to avoid unaligned access */
@@ -667,11 +665,7 @@
 	struct poll_list *stack_pp = NULL;
 
 	/* Do a sanity check on nfds ... */
-	rcu_read_lock();
-	fdt = files_fdtable(current->files);
-	max_fdset = fdt->max_fdset;
-	rcu_read_unlock();
-	if (nfds > max_fdset && nfds > OPEN_MAX)
+	if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
 		return -EINVAL;
 
 	poll_initwait(&table);
diff --git a/fs/super.c b/fs/super.c
index 5c4c94d..6987824 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -199,7 +199,7 @@
  *	success, 0 if we had failed (superblock contents was already dead or
  *	dying when grab_super() had been called).
  */
-static int grab_super(struct super_block *s)
+static int grab_super(struct super_block *s) __releases(sb_lock)
 {
 	s->s_count++;
 	spin_unlock(&sb_lock);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 5dd356c..1d3b5d2 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1621,6 +1621,10 @@
 		goto error_out;
 	}
 
+	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) )
 	{
 		printk("UDF-fs: No fileset found\n");
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index 9e7f859..291948d 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -30,7 +30,6 @@
 	EXTRA_CFLAGS += -DXFS_BLI_TRACE
 	EXTRA_CFLAGS += -DXFS_BMAP_TRACE
 	EXTRA_CFLAGS += -DXFS_BMBT_TRACE
-	EXTRA_CFLAGS += -DXFS_DIR_TRACE
 	EXTRA_CFLAGS += -DXFS_DIR2_TRACE
 	EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
 	EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
index aba7fcf..d597375 100644
--- a/fs/xfs/linux-2.6/kmem.c
+++ b/fs/xfs/linux-2.6/kmem.c
@@ -34,6 +34,14 @@
 	gfp_t	lflags = kmem_flags_convert(flags);
 	void	*ptr;
 
+#ifdef DEBUG
+	if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) {
+		printk(KERN_WARNING "Large %s attempt, size=%ld\n",
+			__FUNCTION__, (long)size);
+		dump_stack();
+	}
+#endif
+
 	do {
 		if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
 			ptr = kmalloc(size, lflags);
@@ -60,6 +68,27 @@
 	return ptr;
 }
 
+void *
+kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize,
+		   unsigned int __nocast flags)
+{
+	void		*ptr;
+	size_t		kmsize = maxsize;
+	unsigned int	kmflags = (flags & ~KM_SLEEP) | KM_NOSLEEP;
+
+	while (!(ptr = kmem_zalloc(kmsize, kmflags))) {
+		if ((kmsize <= minsize) && (flags & KM_NOSLEEP))
+			break;
+		if ((kmsize >>= 1) <= minsize) {
+			kmsize = minsize;
+			kmflags = flags;
+		}
+	}
+	if (ptr)
+		*size = kmsize;
+	return ptr;
+}
+
 void
 kmem_free(void *ptr, size_t size)
 {
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 0e8293c..9ebabdf 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -30,6 +30,7 @@
 #define KM_NOSLEEP	0x0002u
 #define KM_NOFS		0x0004u
 #define KM_MAYFAIL	0x0008u
+#define KM_LARGE	0x0010u
 
 /*
  * We use a special process flag to avoid recursive callbacks into
@@ -41,7 +42,7 @@
 {
 	gfp_t	lflags;
 
-	BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL));
+	BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL|KM_LARGE));
 
 	if (flags & KM_NOSLEEP) {
 		lflags = GFP_ATOMIC | __GFP_NOWARN;
@@ -54,8 +55,9 @@
 }
 
 extern void *kmem_alloc(size_t, unsigned int __nocast);
-extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast);
 extern void *kmem_zalloc(size_t, unsigned int __nocast);
+extern void *kmem_zalloc_greedy(size_t *, size_t, size_t, unsigned int __nocast);
+extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast);
 extern void  kmem_free(void *, size_t);
 
 /*
diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h
index b250900..2009e6d 100644
--- a/fs/xfs/linux-2.6/sema.h
+++ b/fs/xfs/linux-2.6/sema.h
@@ -29,8 +29,6 @@
 
 typedef struct semaphore sema_t;
 
-#define init_sema(sp, val, c, d)	sema_init(sp, val)
-#define initsema(sp, val)		sema_init(sp, val)
 #define initnsema(sp, val, name)	sema_init(sp, val)
 #define psema(sp, b)			down(sp)
 #define vsema(sp)			up(sp)
diff --git a/fs/xfs/linux-2.6/sv.h b/fs/xfs/linux-2.6/sv.h
index 9a8ad48..351a8f4 100644
--- a/fs/xfs/linux-2.6/sv.h
+++ b/fs/xfs/linux-2.6/sv.h
@@ -53,8 +53,6 @@
 	remove_wait_queue(&sv->waiters, &wait);
 }
 
-#define init_sv(sv,type,name,flag) \
-	init_waitqueue_head(&(sv)->waiters)
 #define sv_init(sv,flag,name) \
 	init_waitqueue_head(&(sv)->waiters)
 #define sv_destroy(sv) \
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 34dcb43..09360cf 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -71,7 +71,7 @@
 	int		tag,
 	struct inode	*inode,
 	struct page	*page,
-	int		mask)
+	unsigned long	pgoff)
 {
 	xfs_inode_t	*ip;
 	bhv_vnode_t	*vp = vn_from_inode(inode);
@@ -91,7 +91,7 @@
 		(void *)ip,
 		(void *)inode,
 		(void *)page,
-		(void *)((unsigned long)mask),
+		(void *)pgoff,
 		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
 		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
 		(void *)((unsigned long)((isize >> 32) & 0xffffffff)),
@@ -105,7 +105,7 @@
 		(void *)NULL);
 }
 #else
-#define xfs_page_trace(tag, inode, page, mask)
+#define xfs_page_trace(tag, inode, page, pgoff)
 #endif
 
 /*
@@ -1197,7 +1197,7 @@
 		.nr_to_write = 1,
 	};
 
-	xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask);
+	xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, 0);
 
 	if (!page_has_buffers(page))
 		return 0;
@@ -1356,7 +1356,6 @@
 		ioend->io_size = size;
 		xfs_finish_ioend(ioend);
 	} else {
-		ASSERT(size >= 0);
 		xfs_destroy_ioend(ioend);
 	}
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 2af528d..9bbadaf 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -318,8 +318,12 @@
 		if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
 			free_address(bp->b_addr - bp->b_offset);
 
-		for (i = 0; i < bp->b_page_count; i++)
-			page_cache_release(bp->b_pages[i]);
+		for (i = 0; i < bp->b_page_count; i++) {
+			struct page	*page = bp->b_pages[i];
+
+			ASSERT(!PagePrivate(page));
+			page_cache_release(page);
+		}
 		_xfs_buf_free_pages(bp);
 	} else if (bp->b_flags & _XBF_KMEM_ALLOC) {
 		 /*
@@ -400,6 +404,7 @@
 		nbytes = min_t(size_t, size, PAGE_CACHE_SIZE - offset);
 		size -= nbytes;
 
+		ASSERT(!PagePrivate(page));
 		if (!PageUptodate(page)) {
 			page_count--;
 			if (blocksize >= PAGE_CACHE_SIZE) {
@@ -768,7 +773,7 @@
 	_xfs_buf_initialize(bp, target, 0, len, 0);
 
  try_again:
-	data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL);
+	data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL | KM_LARGE);
 	if (unlikely(data == NULL))
 		goto fail_free_buf;
 
@@ -1117,10 +1122,10 @@
 	do {
 		struct page	*page = bvec->bv_page;
 
+		ASSERT(!PagePrivate(page));
 		if (unlikely(bp->b_error)) {
 			if (bp->b_flags & XBF_READ)
 				ClearPageUptodate(page);
-			SetPageError(page);
 		} else if (blocksize >= PAGE_CACHE_SIZE) {
 			SetPageUptodate(page);
 		} else if (!PagePrivate(page) &&
@@ -1156,16 +1161,16 @@
 	total_nr_pages = bp->b_page_count;
 	map_i = 0;
 
-	if (bp->b_flags & _XBF_RUN_QUEUES) {
-		bp->b_flags &= ~_XBF_RUN_QUEUES;
-		rw = (bp->b_flags & XBF_READ) ? READ_SYNC : WRITE_SYNC;
-	} else {
-		rw = (bp->b_flags & XBF_READ) ? READ : WRITE;
-	}
-
 	if (bp->b_flags & XBF_ORDERED) {
 		ASSERT(!(bp->b_flags & XBF_READ));
 		rw = WRITE_BARRIER;
+	} else if (bp->b_flags & _XBF_RUN_QUEUES) {
+		ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
+		bp->b_flags &= ~_XBF_RUN_QUEUES;
+		rw = (bp->b_flags & XBF_WRITE) ? WRITE_SYNC : READ_SYNC;
+	} else {
+		rw = (bp->b_flags & XBF_WRITE) ? WRITE :
+		     (bp->b_flags & XBF_READ_AHEAD) ? READA : READ;
 	}
 
 	/* Special code path for reading a sub page size buffer in --
@@ -1681,6 +1686,7 @@
 	xfs_buf_t		*bp, *n;
 	struct list_head	*dwq = &target->bt_delwrite_queue;
 	spinlock_t		*dwlk = &target->bt_delwrite_lock;
+	int			count;
 
 	current->flags |= PF_MEMALLOC;
 
@@ -1696,6 +1702,7 @@
 		schedule_timeout_interruptible(
 			xfs_buf_timer_centisecs * msecs_to_jiffies(10));
 
+		count = 0;
 		age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
 		spin_lock(dwlk);
 		list_for_each_entry_safe(bp, n, dwq, b_list) {
@@ -1711,9 +1718,11 @@
 					break;
 				}
 
-				bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
+				bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|
+						 _XBF_RUN_QUEUES);
 				bp->b_flags |= XBF_WRITE;
-				list_move(&bp->b_list, &tmp);
+				list_move_tail(&bp->b_list, &tmp);
+				count++;
 			}
 		}
 		spin_unlock(dwlk);
@@ -1724,12 +1733,12 @@
 
 			list_del_init(&bp->b_list);
 			xfs_buf_iostrategy(bp);
-
-			blk_run_address_space(target->bt_mapping);
 		}
 
 		if (as_list_len > 0)
 			purge_addresses();
+		if (count)
+			blk_run_address_space(target->bt_mapping);
 
 		clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
 	} while (!kthread_should_stop());
@@ -1767,7 +1776,7 @@
 			continue;
 		}
 
-		list_move(&bp->b_list, &tmp);
+		list_move_tail(&bp->b_list, &tmp);
 	}
 	spin_unlock(dwlk);
 
@@ -1776,7 +1785,7 @@
 	 */
 	list_for_each_entry_safe(bp, n, &tmp, b_list) {
 		xfs_buf_lock(bp);
-		bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
+		bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|_XBF_RUN_QUEUES);
 		bp->b_flags |= XBF_WRITE;
 		if (wait)
 			bp->b_flags &= ~XBF_ASYNC;
@@ -1786,6 +1795,9 @@
 		xfs_buf_iostrategy(bp);
 	}
 
+	if (wait)
+		blk_run_address_space(target->bt_mapping);
+
 	/*
 	 * Remaining list items must be flushed before returning
 	 */
@@ -1797,9 +1809,6 @@
 		xfs_buf_relse(bp);
 	}
 
-	if (wait)
-		blk_run_address_space(target->bt_mapping);
-
 	return pincount;
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 7858703..9dd235c 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -298,11 +298,6 @@
 #define XFS_BUF_UNWRITE(bp)	((bp)->b_flags &= ~XBF_WRITE)
 #define XFS_BUF_ISWRITE(bp)	((bp)->b_flags & XBF_WRITE)
 
-#define XFS_BUF_ISUNINITIAL(bp)	(0)
-#define XFS_BUF_UNUNINITIAL(bp)	(0)
-
-#define XFS_BUF_BP_ISMAPPED(bp)	(1)
-
 #define XFS_BUF_IODONE_FUNC(bp)			((bp)->b_iodone)
 #define XFS_BUF_SET_IODONE_FUNC(bp, func)	((bp)->b_iodone = (func))
 #define XFS_BUF_CLR_IODONE_FUNC(bp)		((bp)->b_iodone = NULL)
@@ -393,8 +388,6 @@
 	return error;
 }
 
-#define XFS_bdwrite(bp)		xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC)
-
 static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
 {
 	bp->b_strat = xfs_bdstrat_cb;
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index 6c162c3..ed3a5e1 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -34,7 +34,7 @@
 	.restrict_chown	= {	0,		1,		1	},
 	.sgid_inherit	= {	0,		0,		1	},
 	.symlink_mode	= {	0,		0,		1	},
-	.panic_mask	= {	0,		0,		127	},
+	.panic_mask	= {	0,		0,		255	},
 	.error_level	= {	0,		3,		11	},
 	.syncd_timer	= {	1*100,		30*100,		7200*100},
 	.stats_clear	= {	0,		0,		1	},
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 6e52a5d..a74f854 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -653,7 +653,7 @@
 STATIC int
 xfs_ioc_space(
 	bhv_desc_t		*bdp,
-	bhv_vnode_t		*vp,
+	struct inode		*inode,
 	struct file		*filp,
 	int			flags,
 	unsigned int		cmd,
@@ -735,7 +735,7 @@
 		    !capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg);
+		return xfs_ioc_space(bdp, inode, filp, ioflags, cmd, arg);
 
 	case XFS_IOC_DIOINFO: {
 		struct dioattr	da;
@@ -763,6 +763,8 @@
 		return xfs_ioc_fsgeometry(mp, arg);
 
 	case XFS_IOC_GETVERSION:
+		return put_user(inode->i_generation, (int __user *)arg);
+
 	case XFS_IOC_GETXFLAGS:
 	case XFS_IOC_SETXFLAGS:
 	case XFS_IOC_FSGETXATTR:
@@ -957,7 +959,7 @@
 STATIC int
 xfs_ioc_space(
 	bhv_desc_t		*bdp,
-	bhv_vnode_t		*vp,
+	struct inode		*inode,
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
@@ -967,13 +969,13 @@
 	int			attr_flags = 0;
 	int			error;
 
-	if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+	if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
 		return -XFS_ERROR(EPERM);
 
 	if (!(filp->f_mode & FMODE_WRITE))
 		return -XFS_ERROR(EBADF);
 
-	if (!VN_ISREG(vp))
+	if (!S_ISREG(inode->i_mode))
 		return -XFS_ERROR(EINVAL);
 
 	if (copy_from_user(&bf, arg, sizeof(bf)))
@@ -1264,13 +1266,6 @@
 		break;
 	}
 
-	case XFS_IOC_GETVERSION: {
-		flags = vn_to_inode(vp)->i_generation;
-		if (copy_to_user(arg, &flags, sizeof(flags)))
-			error = -EFAULT;
-		break;
-	}
-
 	default:
 		error = -ENOTTY;
 		break;
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 22e3b71..3ba814a 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -623,12 +623,27 @@
 {
 	struct inode	*inode = dentry->d_inode;
 	bhv_vnode_t	*vp = vn_from_inode(inode);
-	int		error = 0;
+	bhv_vattr_t	vattr = { .va_mask = XFS_AT_STAT };
+	int		error;
 
-	if (unlikely(vp->v_flag & VMODIFIED))
-		error = vn_revalidate(vp);
-	if (!error)
-		generic_fillattr(inode, stat);
+	error = bhv_vop_getattr(vp, &vattr, ATTR_LAZY, NULL);
+	if (likely(!error)) {
+		stat->size = i_size_read(inode);
+		stat->dev = inode->i_sb->s_dev;
+		stat->rdev = (vattr.va_rdev == 0) ? 0 :
+				MKDEV(sysv_major(vattr.va_rdev) & 0x1ff,
+				      sysv_minor(vattr.va_rdev));
+		stat->mode = vattr.va_mode;
+		stat->nlink = vattr.va_nlink;
+		stat->uid = vattr.va_uid;
+		stat->gid = vattr.va_gid;
+		stat->ino = vattr.va_nodeid;
+		stat->atime = vattr.va_atime;
+		stat->mtime = vattr.va_mtime;
+		stat->ctime = vattr.va_ctime;
+		stat->blocks = vattr.va_nblocks;
+		stat->blksize = vattr.va_blocksize;
+	}
 	return -error;
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index a13f75c..2b0e001 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -148,11 +148,7 @@
 		(current->flags = ((current->flags & ~(f)) | (*(sp) & (f))))
 
 #define NBPP		PAGE_SIZE
-#define DPPSHFT		(PAGE_SHIFT - 9)
 #define NDPP		(1 << (PAGE_SHIFT - 9))
-#define dtop(DD)	(((DD) + NDPP - 1) >> DPPSHFT)
-#define dtopt(DD)	((DD) >> DPPSHFT)
-#define dpoff(DD)	((DD) & (NDPP-1))
 
 #define NBBY		8		/* number of bits per byte */
 #define	NBPC		PAGE_SIZE	/* Number of bytes per click */
@@ -172,8 +168,6 @@
 #define	btoct(x)	((__psunsigned_t)(x)>>BPCSHIFT)
 #define	btoc64(x)	(((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
 #define	btoct64(x)	((__uint64_t)(x)>>BPCSHIFT)
-#define	io_btoc(x)	(((__psunsigned_t)(x)+(IO_NBPC-1))>>IO_BPCSHIFT)
-#define	io_btoct(x)	((__psunsigned_t)(x)>>IO_BPCSHIFT)
 
 /* off_t bytes to clicks */
 #define offtoc(x)       (((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
@@ -186,7 +180,6 @@
 #define	ctob(x)		((__psunsigned_t)(x)<<BPCSHIFT)
 #define btoct(x)        ((__psunsigned_t)(x)>>BPCSHIFT)
 #define	ctob64(x)	((__uint64_t)(x)<<BPCSHIFT)
-#define	io_ctob(x)	((__psunsigned_t)(x)<<IO_BPCSHIFT)
 
 /* bytes to clicks */
 #define btoc(x)         (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT)
@@ -339,4 +332,11 @@
 	return(x * y);
 }
 
+static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
+{
+	x += y - 1;
+	do_div(x, y);
+	return x;
+}
+
 #endif /* __XFS_LINUX__ */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index ee788b1..55992b4 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -270,12 +270,12 @@
 		}
 	}
 
-	if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp)))
-		bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
-						-1, FI_REMAPF_LOCKED);
-
-	if (unlikely(ioflags & IO_ISDIRECT))
+	if (unlikely(ioflags & IO_ISDIRECT)) {
+		if (VN_CACHED(vp))
+			bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
+						 -1, FI_REMAPF_LOCKED);
 		mutex_unlock(&inode->i_mutex);
+	}
 
 	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
 				(void *)iovp, segs, *offset, ioflags);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 9df9ed3..38c4d12 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -227,7 +227,9 @@
 		xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
 		xfs_set_inodeops(inode);
 
+		spin_lock(&ip->i_flags_lock);
 		ip->i_flags &= ~XFS_INEW;
+		spin_unlock(&ip->i_flags_lock);
 		barrier();
 
 		unlock_new_inode(inode);
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 91fc2c4..da255bd 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -79,7 +79,7 @@
 #define VFS_RDONLY		0x0001	/* read-only vfs */
 #define VFS_GRPID		0x0002	/* group-ID assigned from directory */
 #define VFS_DMI			0x0004	/* filesystem has the DMI enabled */
-#define VFS_UMOUNT		0x0008	/* unmount in progress */
+/* ---- VFS_UMOUNT ----		0x0008	-- unneeded, fixed via kthread APIs */
 #define VFS_32BITINODES		0x0010	/* do not use inums above 32 bits */
 #define VFS_END			0x0010	/* max flag */
 
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index c42b322..515f5fd 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -85,8 +85,6 @@
 #define VN_BHV_HEAD(vp)			((bhv_head_t *)(&((vp)->v_bh)))
 #define vn_bhv_head_init(bhp,name)	bhv_head_init(bhp,name)
 #define vn_bhv_remove(bhp,bdp)		bhv_remove(bhp,bdp)
-#define vn_bhv_lookup(bhp,ops)		bhv_lookup(bhp,ops)
-#define vn_bhv_lookup_unlocked(bhp,ops) bhv_lookup_unlocked(bhp,ops)
 
 /*
  * Vnode to Linux inode mapping.
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 5b2dcc5..33ad5af 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -382,18 +382,6 @@
 
 
 /*
- * The transaction with the dquot locked has aborted.  The dquot
- * must not be dirty within the transaction.  We simply unlock just
- * as if the transaction had been cancelled.
- */
-STATIC void
-xfs_qm_dquot_logitem_abort(
-	xfs_dq_logitem_t    *ql)
-{
-	xfs_qm_dquot_logitem_unlock(ql);
-}
-
-/*
  * this needs to stamp an lsn into the dquot, I think.
  * rpc's that look at user dquot's would then have to
  * push on the dependency recorded in the dquot
@@ -426,7 +414,6 @@
 	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_qm_dquot_logitem_committed,
 	.iop_push	= (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_push,
-	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_abort,
 	.iop_pushbuf	= (void(*)(xfs_log_item_t*))
 					xfs_qm_dquot_logitem_pushbuf,
 	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
@@ -559,17 +546,6 @@
 }
 
 /*
- * The transaction of which this QUOTAOFF is a part has been aborted.
- * Just clean up after ourselves.
- * Shouldn't this never happen in the case of qoffend logitems? XXX
- */
-STATIC void
-xfs_qm_qoff_logitem_abort(xfs_qoff_logitem_t *qf)
-{
-	kmem_free(qf, sizeof(xfs_qoff_logitem_t));
-}
-
-/*
  * There isn't much you can do to push on an quotaoff item.  It is simply
  * stuck waiting for the log to be flushed to disk.
  */
@@ -644,7 +620,6 @@
 	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_qm_qoffend_logitem_committed,
 	.iop_push	= (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_push,
-	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_abort,
 	.iop_pushbuf	= NULL,
 	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_qm_qoffend_logitem_committing
@@ -667,7 +642,6 @@
 	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_qm_qoff_logitem_committed,
 	.iop_push	= (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_push,
-	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_abort,
 	.iop_pushbuf	= NULL,
 	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_qm_qoff_logitem_committing
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index e23e455..7c6a3a5 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -112,17 +112,17 @@
 {
 	xfs_dqhash_t	*udqhash, *gdqhash;
 	xfs_qm_t	*xqm;
-	uint		i, hsize, flags = KM_SLEEP | KM_MAYFAIL;
+	size_t		hsize;
+	uint		i;
 
 	/*
 	 * Initialize the dquot hash tables.
 	 */
-	hsize = XFS_QM_HASHSIZE_HIGH;
-	while (!(udqhash = kmem_zalloc(hsize * sizeof(xfs_dqhash_t), flags))) {
-		if ((hsize >>= 1) <= XFS_QM_HASHSIZE_LOW)
-			flags = KM_SLEEP;
-	}
-	gdqhash = kmem_zalloc(hsize * sizeof(xfs_dqhash_t), KM_SLEEP);
+	udqhash = kmem_zalloc_greedy(&hsize,
+				     XFS_QM_HASHSIZE_LOW, XFS_QM_HASHSIZE_HIGH,
+				     KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+	gdqhash = kmem_zalloc(hsize, KM_SLEEP | KM_LARGE);
+	hsize /= sizeof(xfs_dqhash_t);
 	ndquot = hsize << 8;
 
 	xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 4568deb..689407d 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -56,12 +56,6 @@
 #define XFS_QM_HASHSIZE_HIGH		((NBPP * 4) / sizeof(xfs_dqhash_t))
 
 /*
- * We output a cmn_err when quotachecking a quota file with more than
- * this many fsbs.
- */
-#define XFS_QM_BIG_QCHECK_NBLKS		500
-
-/*
  * This defines the unit of allocation of dquots.
  * Currently, it is just one file system block, and a 4K blk contains 30
  * (136 * 30 = 4080) dquots. It's probably not worth trying to make
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index b7ddd04..a8b85e2 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -75,7 +75,6 @@
 
 #define xfs_qm_freelist_lock(qm)	XQMLCK(&((qm)->qm_dqfreelist))
 #define xfs_qm_freelist_unlock(qm)	XQMUNLCK(&((qm)->qm_dqfreelist))
-#define XFS_QM_IS_FREELIST_LOCKED(qm)	XQMISLCKD(&((qm)->qm_dqfreelist))
 
 /*
  * Hash into a bucket in the dquot hash table, based on <mp, id>.
@@ -170,6 +169,5 @@
 #define DQFLAGTO_TYPESTR(d)	(((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
 				 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
 				 (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
-#define DQFLAGTO_DIRTYSTR(d)	(XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
 
 #endif	/* __XFS_QUOTA_PRIV_H__ */
diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
index addf5a7..5cf2e86 100644
--- a/fs/xfs/support/ktrace.c
+++ b/fs/xfs/support/ktrace.c
@@ -75,7 +75,7 @@
 							    sleep);
 	} else {
 		ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
-							    sleep);
+							    sleep | KM_LARGE);
 	}
 
 	if (ktep == NULL) {
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index dc2361d..9ece7f87 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -150,7 +150,7 @@
 #define	XFS_BUF_TO_AGFL(bp)	((xfs_agfl_t *)XFS_BUF_PTR(bp))
 
 typedef struct xfs_agfl {
-	xfs_agblock_t	agfl_bno[1];	/* actually XFS_AGFL_SIZE(mp) */
+	__be32		agfl_bno[1];	/* actually XFS_AGFL_SIZE(mp) */
 } xfs_agfl_t;
 
 /*
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index d2bbcd8..e80dda3 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -1477,8 +1477,10 @@
 	/*
 	 * Can't allocate from the freelist for some reason.
 	 */
-	else
+	else {
+		fbno = NULLAGBLOCK;
 		flen = 0;
+	}
 	/*
 	 * Can't do the allocation, give up.
 	 */
@@ -2021,7 +2023,7 @@
 	/*
 	 * Get the block number and update the data structures.
 	 */
-	bno = INT_GET(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)], ARCH_CONVERT);
+	bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
 	be32_add(&agf->agf_flfirst, 1);
 	xfs_trans_brelse(tp, agflbp);
 	if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
@@ -2108,7 +2110,7 @@
 {
 	xfs_agf_t		*agf;	/* a.g. freespace structure */
 	xfs_agfl_t		*agfl;	/* a.g. free block array */
-	xfs_agblock_t		*blockp;/* pointer to array entry */
+	__be32			*blockp;/* pointer to array entry */
 	int			error;
 #ifdef XFS_ALLOC_TRACE
 	static char		fname[] = "xfs_alloc_put_freelist";
@@ -2132,7 +2134,7 @@
 	pag->pagf_flcount++;
 	ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
 	blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
-	INT_SET(*blockp, ARCH_CONVERT, bno);
+	*blockp = cpu_to_be32(bno);
 	TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
 	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
 	xfs_trans_log_buf(tp, agflbp,
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 7446556..74cadf9 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -92,6 +92,7 @@
 	xfs_alloc_key_t		*rkp;	/* right block key pointer */
 	xfs_alloc_ptr_t		*rpp;	/* right block address pointer */
 	int			rrecs=0;	/* number of records in right block */
+	int			numrecs;
 	xfs_alloc_rec_t		*rrp;	/* right block record pointer */
 	xfs_btree_cur_t		*tcur;	/* temporary btree cursor */
 
@@ -115,7 +116,8 @@
 	/*
 	 * Fail if we're off the end of the block.
 	 */
-	if (ptr > be16_to_cpu(block->bb_numrecs)) {
+	numrecs = be16_to_cpu(block->bb_numrecs);
+	if (ptr > numrecs) {
 		*stat = 0;
 		return 0;
 	}
@@ -129,18 +131,18 @@
 		lkp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
 		lpp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
 #ifdef DEBUG
-		for (i = ptr; i < be16_to_cpu(block->bb_numrecs); i++) {
+		for (i = ptr; i < numrecs; i++) {
 			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level)))
 				return error;
 		}
 #endif
-		if (ptr < be16_to_cpu(block->bb_numrecs)) {
+		if (ptr < numrecs) {
 			memmove(&lkp[ptr - 1], &lkp[ptr],
-				(be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lkp));
+				(numrecs - ptr) * sizeof(*lkp));
 			memmove(&lpp[ptr - 1], &lpp[ptr],
-				(be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lpp));
-			xfs_alloc_log_ptrs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
-			xfs_alloc_log_keys(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
+				(numrecs - ptr) * sizeof(*lpp));
+			xfs_alloc_log_ptrs(cur, bp, ptr, numrecs - 1);
+			xfs_alloc_log_keys(cur, bp, ptr, numrecs - 1);
 		}
 	}
 	/*
@@ -149,10 +151,10 @@
 	 */
 	else {
 		lrp = XFS_ALLOC_REC_ADDR(block, 1, cur);
-		if (ptr < be16_to_cpu(block->bb_numrecs)) {
+		if (ptr < numrecs) {
 			memmove(&lrp[ptr - 1], &lrp[ptr],
-				(be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lrp));
-			xfs_alloc_log_recs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
+				(numrecs - ptr) * sizeof(*lrp));
+			xfs_alloc_log_recs(cur, bp, ptr, numrecs - 1);
 		}
 		/*
 		 * If it's the first record in the block, we'll need a key
@@ -167,7 +169,8 @@
 	/*
 	 * Decrement and log the number of entries in the block.
 	 */
-	be16_add(&block->bb_numrecs, -1);
+	numrecs--;
+	block->bb_numrecs = cpu_to_be16(numrecs);
 	xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
 	/*
 	 * See if the longest free extent in the allocation group was
@@ -181,14 +184,14 @@
 	if (level == 0 &&
 	    cur->bc_btnum == XFS_BTNUM_CNT &&
 	    be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK &&
-	    ptr > be16_to_cpu(block->bb_numrecs)) {
-		ASSERT(ptr == be16_to_cpu(block->bb_numrecs) + 1);
+	    ptr > numrecs) {
+		ASSERT(ptr == numrecs + 1);
 		/*
 		 * There are still records in the block.  Grab the size
 		 * from the last one.
 		 */
-		if (be16_to_cpu(block->bb_numrecs)) {
-			rrp = XFS_ALLOC_REC_ADDR(block, be16_to_cpu(block->bb_numrecs), cur);
+		if (numrecs) {
+			rrp = XFS_ALLOC_REC_ADDR(block, numrecs, cur);
 			agf->agf_longest = rrp->ar_blockcount;
 		}
 		/*
@@ -211,7 +214,7 @@
 		 * and it's NOT the leaf level,
 		 * then we can get rid of this level.
 		 */
-		if (be16_to_cpu(block->bb_numrecs) == 1 && level > 0) {
+		if (numrecs == 1 && level > 0) {
 			/*
 			 * lpp is still set to the first pointer in the block.
 			 * Make it the new root of the btree.
@@ -267,7 +270,7 @@
 	 * If the number of records remaining in the block is at least
 	 * the minimum, we're done.
 	 */
-	if (be16_to_cpu(block->bb_numrecs) >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
+	if (numrecs >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
 		if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
 			return error;
 		*stat = 1;
@@ -419,19 +422,21 @@
 	 * See if we can join with the left neighbor block.
 	 */
 	if (lbno != NULLAGBLOCK &&
-	    lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
+	    lrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 		/*
 		 * Set "right" to be the starting block,
 		 * "left" to be the left neighbor.
 		 */
 		rbno = bno;
 		right = block;
+		rrecs = be16_to_cpu(right->bb_numrecs);
 		rbp = bp;
 		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
 				cur->bc_private.a.agno, lbno, 0, &lbp,
 				XFS_ALLOC_BTREE_REF)))
 			return error;
 		left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
+		lrecs = be16_to_cpu(left->bb_numrecs);
 		if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
 			return error;
 	}
@@ -439,20 +444,21 @@
 	 * If that won't work, see if we can join with the right neighbor block.
 	 */
 	else if (rbno != NULLAGBLOCK &&
-		 rrecs + be16_to_cpu(block->bb_numrecs) <=
-		  XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
+		 rrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 		/*
 		 * Set "left" to be the starting block,
 		 * "right" to be the right neighbor.
 		 */
 		lbno = bno;
 		left = block;
+		lrecs = be16_to_cpu(left->bb_numrecs);
 		lbp = bp;
 		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
 				cur->bc_private.a.agno, rbno, 0, &rbp,
 				XFS_ALLOC_BTREE_REF)))
 			return error;
 		right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
+		rrecs = be16_to_cpu(right->bb_numrecs);
 		if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
 			return error;
 	}
@@ -474,34 +480,28 @@
 		/*
 		 * It's a non-leaf.  Move keys and pointers.
 		 */
-		lkp = XFS_ALLOC_KEY_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
-		lpp = XFS_ALLOC_PTR_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
+		lkp = XFS_ALLOC_KEY_ADDR(left, lrecs + 1, cur);
+		lpp = XFS_ALLOC_PTR_ADDR(left, lrecs + 1, cur);
 		rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
 		rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
 #ifdef DEBUG
-		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
+		for (i = 0; i < rrecs; i++) {
 			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level)))
 				return error;
 		}
 #endif
-		memcpy(lkp, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*lkp));
-		memcpy(lpp, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*lpp));
-		xfs_alloc_log_keys(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
-				   be16_to_cpu(left->bb_numrecs) +
-				   be16_to_cpu(right->bb_numrecs));
-		xfs_alloc_log_ptrs(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
-				   be16_to_cpu(left->bb_numrecs) +
-				   be16_to_cpu(right->bb_numrecs));
+		memcpy(lkp, rkp, rrecs * sizeof(*lkp));
+		memcpy(lpp, rpp, rrecs * sizeof(*lpp));
+		xfs_alloc_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs);
+		xfs_alloc_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs);
 	} else {
 		/*
 		 * It's a leaf.  Move records.
 		 */
-		lrp = XFS_ALLOC_REC_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
+		lrp = XFS_ALLOC_REC_ADDR(left, lrecs + 1, cur);
 		rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
-		memcpy(lrp, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*lrp));
-		xfs_alloc_log_recs(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
-				   be16_to_cpu(left->bb_numrecs) +
-				   be16_to_cpu(right->bb_numrecs));
+		memcpy(lrp, rrp, rrecs * sizeof(*lrp));
+		xfs_alloc_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs);
 	}
 	/*
 	 * If we joined with the left neighbor, set the buffer in the
@@ -509,7 +509,7 @@
 	 */
 	if (bp != lbp) {
 		xfs_btree_setbuf(cur, level, lbp);
-		cur->bc_ptrs[level] += be16_to_cpu(left->bb_numrecs);
+		cur->bc_ptrs[level] += lrecs;
 	}
 	/*
 	 * If we joined with the right neighbor and there's a level above
@@ -521,7 +521,8 @@
 	/*
 	 * Fix up the number of records in the surviving block.
 	 */
-	be16_add(&left->bb_numrecs, be16_to_cpu(right->bb_numrecs));
+	lrecs += rrecs;
+	left->bb_numrecs = cpu_to_be16(lrecs);
 	/*
 	 * Fix up the right block pointer in the surviving block, and log it.
 	 */
@@ -608,6 +609,7 @@
 	xfs_btree_cur_t		*ncur;	/* new cursor to be used at next lvl */
 	xfs_alloc_key_t		nkey;	/* new key value, from split */
 	xfs_alloc_rec_t		nrec;	/* new record value, for caller */
+	int			numrecs;
 	int			optr;	/* old ptr value */
 	xfs_alloc_ptr_t		*pp;	/* pointer to btree addresses */
 	int			ptr;	/* index in btree block for this rec */
@@ -653,13 +655,14 @@
 	 */
 	bp = cur->bc_bufs[level];
 	block = XFS_BUF_TO_ALLOC_BLOCK(bp);
+	numrecs = be16_to_cpu(block->bb_numrecs);
 #ifdef DEBUG
 	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
 		return error;
 	/*
 	 * Check that the new entry is being inserted in the right place.
 	 */
-	if (ptr <= be16_to_cpu(block->bb_numrecs)) {
+	if (ptr <= numrecs) {
 		if (level == 0) {
 			rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
 			xfs_btree_check_rec(cur->bc_btnum, recp, rp);
@@ -670,12 +673,12 @@
 	}
 #endif
 	nbno = NULLAGBLOCK;
-	ncur = (xfs_btree_cur_t *)0;
+	ncur = NULL;
 	/*
 	 * If the block is full, we can't insert the new entry until we
 	 * make the block un-full.
 	 */
-	if (be16_to_cpu(block->bb_numrecs) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
+	if (numrecs == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
 		/*
 		 * First, try shifting an entry to the right neighbor.
 		 */
@@ -729,6 +732,7 @@
 	 * At this point we know there's room for our new entry in the block
 	 * we're pointing at.
 	 */
+	numrecs = be16_to_cpu(block->bb_numrecs);
 	if (level > 0) {
 		/*
 		 * It's a non-leaf entry.  Make a hole for the new data
@@ -737,15 +741,15 @@
 		kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
 		pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
 #ifdef DEBUG
-		for (i = be16_to_cpu(block->bb_numrecs); i >= ptr; i--) {
+		for (i = numrecs; i >= ptr; i--) {
 			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level)))
 				return error;
 		}
 #endif
 		memmove(&kp[ptr], &kp[ptr - 1],
-			(be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*kp));
+			(numrecs - ptr + 1) * sizeof(*kp));
 		memmove(&pp[ptr], &pp[ptr - 1],
-			(be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*pp));
+			(numrecs - ptr + 1) * sizeof(*pp));
 #ifdef DEBUG
 		if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
 			return error;
@@ -755,11 +759,12 @@
 		 */
 		kp[ptr - 1] = key;
 		pp[ptr - 1] = cpu_to_be32(*bnop);
-		be16_add(&block->bb_numrecs, 1);
-		xfs_alloc_log_keys(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
-		xfs_alloc_log_ptrs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
+		numrecs++;
+		block->bb_numrecs = cpu_to_be16(numrecs);
+		xfs_alloc_log_keys(cur, bp, ptr, numrecs);
+		xfs_alloc_log_ptrs(cur, bp, ptr, numrecs);
 #ifdef DEBUG
-		if (ptr < be16_to_cpu(block->bb_numrecs))
+		if (ptr < numrecs)
 			xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1,
 				kp + ptr);
 #endif
@@ -769,16 +774,17 @@
 		 */
 		rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
 		memmove(&rp[ptr], &rp[ptr - 1],
-			(be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*rp));
+			(numrecs - ptr + 1) * sizeof(*rp));
 		/*
 		 * Now stuff the new record in, bump numrecs
 		 * and log the new data.
 		 */
-		rp[ptr - 1] = *recp; /* INT_: struct copy */
-		be16_add(&block->bb_numrecs, 1);
-		xfs_alloc_log_recs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
+		rp[ptr - 1] = *recp;
+		numrecs++;
+		block->bb_numrecs = cpu_to_be16(numrecs);
+		xfs_alloc_log_recs(cur, bp, ptr, numrecs);
 #ifdef DEBUG
-		if (ptr < be16_to_cpu(block->bb_numrecs))
+		if (ptr < numrecs)
 			xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1,
 				rp + ptr);
 #endif
@@ -819,8 +825,8 @@
 	 */
 	*bnop = nbno;
 	if (nbno != NULLAGBLOCK) {
-		*recp = nrec; /* INT_: struct copy */
-		*curp = ncur; /* INT_: struct copy */
+		*recp = nrec;
+		*curp = ncur;
 	}
 	*stat = 1;
 	return 0;
@@ -981,7 +987,7 @@
 		 */
 		bp = cur->bc_bufs[level];
 		if (bp && XFS_BUF_ADDR(bp) != d)
-			bp = (xfs_buf_t *)0;
+			bp = NULL;
 		if (!bp) {
 			/*
 			 * Need to get a new buffer.  Read it, then
@@ -1229,7 +1235,7 @@
 		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level)))
 			return error;
 #endif
-		*lpp = *rpp; /* INT_: copy */
+		*lpp = *rpp;
 		xfs_alloc_log_ptrs(cur, lbp, nrec, nrec);
 		xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp);
 	}
@@ -1406,8 +1412,8 @@
 
 		kp = XFS_ALLOC_KEY_ADDR(new, 1, cur);
 		if (be16_to_cpu(left->bb_level) > 0) {
-			kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); /* INT_: structure copy */
-			kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur);/* INT_: structure copy */
+			kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur);
+			kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur);
 		} else {
 			xfs_alloc_rec_t	*rp;	/* btree record pointer */
 
@@ -1527,8 +1533,8 @@
 		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*lpp), level)))
 			return error;
 #endif
-		*rkp = *lkp; /* INT_: copy */
-		*rpp = *lpp; /* INT_: copy */
+		*rkp = *lkp;
+		*rpp = *lpp;
 		xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
 		xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
 		xfs_btree_check_key(cur->bc_btnum, rkp, rkp + 1);
@@ -2044,7 +2050,7 @@
 	nbno = NULLAGBLOCK;
 	nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
 	nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
-	ncur = (xfs_btree_cur_t *)0;
+	ncur = NULL;
 	pcur = cur;
 	/*
 	 * Loop going up the tree, starting at the leaf level.
@@ -2076,7 +2082,7 @@
 		 */
 		if (ncur) {
 			pcur = ncur;
-			ncur = (xfs_btree_cur_t *)0;
+			ncur = NULL;
 		}
 	} while (nbno != NULLAGBLOCK);
 	*stat = i;
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 1a210104..9ada7bd 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -91,7 +91,6 @@
 /*
  * Routines to manipulate out-of-line attribute values.
  */
-STATIC int xfs_attr_rmtval_get(xfs_da_args_t *args);
 STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
 STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
 
@@ -180,7 +179,7 @@
 	return(error);
 }
 
-STATIC int
+int
 xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
 		 char *value, int valuelen, int flags)
 {
@@ -440,7 +439,7 @@
  * Generic handler routine to remove a name from an attribute list.
  * Transitions attribute list from Btree to shortform as necessary.
  */
-STATIC int
+int
 xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
 {
 	xfs_da_args_t	args;
@@ -591,6 +590,110 @@
 	return xfs_attr_remove_int(dp, name, namelen, flags);
 }
 
+int								/* error */
+xfs_attr_list_int(xfs_attr_list_context_t *context)
+{
+	int error;
+	xfs_inode_t *dp = context->dp;
+
+	/*
+	 * Decide on what work routines to call based on the inode size.
+	 */
+	if (XFS_IFORK_Q(dp) == 0 ||
+	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+	     dp->i_d.di_anextents == 0)) {
+		error = 0;
+	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+		error = xfs_attr_shortform_list(context);
+	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
+		error = xfs_attr_leaf_list(context);
+	} else {
+		error = xfs_attr_node_list(context);
+	}
+	return error;
+}
+
+#define	ATTR_ENTBASESIZE		/* minimum bytes used by an attr */ \
+	(((struct attrlist_ent *) 0)->a_name - (char *) 0)
+#define	ATTR_ENTSIZE(namelen)		/* actual bytes used by an attr */ \
+	((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
+	 & ~(sizeof(u_int32_t)-1))
+
+/*
+ * Format an attribute and copy it out to the user's buffer.
+ * Take care to check values and protect against them changing later,
+ * we may be reading them directly out of a user buffer.
+ */
+/*ARGSUSED*/
+STATIC int
+xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp,
+		     char *name, int namelen,
+		     int valuelen, char *value)
+{
+	attrlist_ent_t *aep;
+	int arraytop;
+
+	ASSERT(!(context->flags & ATTR_KERNOVAL));
+	ASSERT(context->count >= 0);
+	ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
+	ASSERT(context->firstu >= sizeof(*context->alist));
+	ASSERT(context->firstu <= context->bufsize);
+
+	arraytop = sizeof(*context->alist) +
+			context->count * sizeof(context->alist->al_offset[0]);
+	context->firstu -= ATTR_ENTSIZE(namelen);
+	if (context->firstu < arraytop) {
+		xfs_attr_trace_l_c("buffer full", context);
+		context->alist->al_more = 1;
+		context->seen_enough = 1;
+		return 1;
+	}
+
+	aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
+	aep->a_valuelen = valuelen;
+	memcpy(aep->a_name, name, namelen);
+	aep->a_name[ namelen ] = 0;
+	context->alist->al_offset[ context->count++ ] = context->firstu;
+	context->alist->al_count = context->count;
+	xfs_attr_trace_l_c("add", context);
+	return 0;
+}
+
+STATIC int
+xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp,
+		     char *name, int namelen,
+		     int valuelen, char *value)
+{
+	char *offset;
+	int arraytop;
+
+	ASSERT(context->count >= 0);
+
+	arraytop = context->count + namesp->attr_namelen + namelen + 1;
+	if (arraytop > context->firstu) {
+		context->count = -1;	/* insufficient space */
+		return 1;
+	}
+	offset = (char *)context->alist + context->count;
+	strncpy(offset, namesp->attr_name, namesp->attr_namelen);
+	offset += namesp->attr_namelen;
+	strncpy(offset, name, namelen);			/* real name */
+	offset += namelen;
+	*offset = '\0';
+	context->count += namesp->attr_namelen + namelen + 1;
+	return 0;
+}
+
+/*ARGSUSED*/
+STATIC int
+xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
+		     char *name, int namelen,
+		     int valuelen, char *value)
+{
+	context->count += namesp->attr_namelen + namelen + 1;
+	return 0;
+}
+
 /*
  * Generate a list of extended attribute names and optionally
  * also value lengths.  Positive return value follows the XFS
@@ -615,13 +718,13 @@
 		return(XFS_ERROR(EINVAL));
 	if ((cursor->initted == 0) &&
 	    (cursor->hashval || cursor->blkno || cursor->offset))
-		return(XFS_ERROR(EINVAL));
+		return XFS_ERROR(EINVAL);
 
 	/*
 	 * Check for a properly aligned buffer.
 	 */
 	if (((long)buffer) & (sizeof(int)-1))
-		return(XFS_ERROR(EFAULT));
+		return XFS_ERROR(EFAULT);
 	if (flags & ATTR_KERNOVAL)
 		bufsize = 0;
 
@@ -634,53 +737,47 @@
 	context.dupcnt = 0;
 	context.resynch = 1;
 	context.flags = flags;
-	if (!(flags & ATTR_KERNAMELS)) {
+	context.seen_enough = 0;
+	context.alist = (attrlist_t *)buffer;
+	context.put_value = 0;
+
+	if (flags & ATTR_KERNAMELS) {
+		context.bufsize = bufsize;
+		context.firstu = context.bufsize;
+		if (flags & ATTR_KERNOVAL)
+			context.put_listent = xfs_attr_kern_list_sizes;
+		else
+			context.put_listent = xfs_attr_kern_list;
+	} else {
 		context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
 		context.firstu = context.bufsize;
-		context.alist = (attrlist_t *)buffer;
 		context.alist->al_count = 0;
 		context.alist->al_more = 0;
 		context.alist->al_offset[0] = context.bufsize;
-	}
-	else {
-		context.bufsize = bufsize;
-		context.firstu = context.bufsize;
-		context.alist = (attrlist_t *)buffer;
+		context.put_listent = xfs_attr_put_listent;
 	}
 
 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
-		return (EIO);
+		return EIO;
 
 	xfs_ilock(dp, XFS_ILOCK_SHARED);
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
 	xfs_attr_trace_l_c("syscall start", &context);
-	if (XFS_IFORK_Q(dp) == 0 ||
-	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
-	     dp->i_d.di_anextents == 0)) {
-		error = 0;
-	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
-		error = xfs_attr_shortform_list(&context);
-	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
-		error = xfs_attr_leaf_list(&context);
-	} else {
-		error = xfs_attr_node_list(&context);
-	}
+
+	error = xfs_attr_list_int(&context);
+
 	xfs_iunlock(dp, XFS_ILOCK_SHARED);
 	xfs_attr_trace_l_c("syscall end", &context);
 
-	if (!(context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS))) {
-		ASSERT(error >= 0);
-	}
-	else {	/* must return negated buffer size or the error */
+	if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) {
+		/* must return negated buffer size or the error */
 		if (context.count < 0)
 			error = XFS_ERROR(ERANGE);
 		else
 			error = -context.count;
-	}
+	} else
+		ASSERT(error >= 0);
 
-	return(error);
+	return error;
 }
 
 int								/* error */
@@ -1122,19 +1219,19 @@
 	context->cursor->blkno = 0;
 	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
 	if (error)
-		return(error);
+		return XFS_ERROR(error);
 	ASSERT(bp != NULL);
 	leaf = bp->data;
 	if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) {
 		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
 				     context->dp->i_mount, leaf);
 		xfs_da_brelse(NULL, bp);
-		return(XFS_ERROR(EFSCORRUPTED));
+		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-	(void)xfs_attr_leaf_list_int(bp, context);
+	error = xfs_attr_leaf_list_int(bp, context);
 	xfs_da_brelse(NULL, bp);
-	return(0);
+	return XFS_ERROR(error);
 }
 
 
@@ -1858,8 +1955,12 @@
 			return(XFS_ERROR(EFSCORRUPTED));
 		}
 		error = xfs_attr_leaf_list_int(bp, context);
-		if (error || !leaf->hdr.info.forw)
-			break;	/* not really an error, buffer full or EOF */
+		if (error) {
+			xfs_da_brelse(NULL, bp);
+			return error;
+		}
+		if (context->seen_enough || leaf->hdr.info.forw == 0)
+			break;
 		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
 		xfs_da_brelse(NULL, bp);
 		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
@@ -1886,7 +1987,7 @@
  * Read the value associated with an attribute from the out-of-line buffer
  * that we stored it in.
  */
-STATIC int
+int
 xfs_attr_rmtval_get(xfs_da_args_t *args)
 {
 	xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE];
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index 981633f..783977d 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -37,6 +37,7 @@
 
 struct cred;
 struct bhv_vnode;
+struct xfs_attr_list_context;
 
 typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int);
 typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int);
@@ -160,13 +161,16 @@
  */
 int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *);
 int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *);
+int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int);
 int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *);
-int xfs_attr_list(bhv_desc_t *, char *, int, int,
-			 struct attrlist_cursor_kern *, struct cred *);
+int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int);
+int xfs_attr_list(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *);
+int xfs_attr_list_int(struct xfs_attr_list_context *);
 int xfs_attr_inactive(struct xfs_inode *dp);
 
 int xfs_attr_shortform_getvalue(struct xfs_da_args *);
 int xfs_attr_fetch(struct xfs_inode *, const char *, int,
 			char *, int *, int, struct cred *);
+int xfs_attr_rmtval_get(struct xfs_da_args *args);
 
 #endif	/* __XFS_ATTR_H__ */
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 9455051..9719bbe 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -89,9 +89,46 @@
 					 int dst_start, int move_count,
 					 xfs_mount_t *mp);
 STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
-STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
-			     attrnames_t *, char *name, int namelen,
-			     int valuelen);
+
+/*========================================================================
+ * Namespace helper routines
+ *========================================================================*/
+
+STATIC inline attrnames_t *
+xfs_attr_flags_namesp(int flags)
+{
+	return ((flags & XFS_ATTR_SECURE) ? &attr_secure:
+		  ((flags & XFS_ATTR_ROOT) ? &attr_trusted : &attr_user));
+}
+
+/*
+ * If namespace bits don't match return 0.
+ * If all match then return 1.
+ */
+STATIC inline int
+xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
+{
+	return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
+}
+
+/*
+ * If namespace bits don't match and we don't have an override for it
+ * then return 0.
+ * If all match or are overridable then return 1.
+ */
+STATIC inline int
+xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags)
+{
+	if (((arg_flags & ATTR_SECURE) == 0) !=
+	    ((ondisk_flags & XFS_ATTR_SECURE) == 0) &&
+	    !(arg_flags & ATTR_KERNORMALS))
+		return 0;
+	if (((arg_flags & ATTR_ROOT) == 0) !=
+	    ((ondisk_flags & XFS_ATTR_ROOT) == 0) &&
+	    !(arg_flags & ATTR_KERNROOTLS))
+		return 0;
+	return 1;
+}
 
 
 /*========================================================================
@@ -228,11 +265,7 @@
 			continue;
 		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
 			continue;
-		if (((args->flags & ATTR_SECURE) != 0) !=
-		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
-			continue;
-		if (((args->flags & ATTR_ROOT) != 0) !=
-		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
+		if (!xfs_attr_namesp_match(args->flags, sfe->flags))
 			continue;
 		ASSERT(0);
 #endif
@@ -246,8 +279,7 @@
 
 	sfe->namelen = args->namelen;
 	sfe->valuelen = args->valuelen;
-	sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
-			((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
+	sfe->flags = XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);
 	memcpy(sfe->nameval, args->name, args->namelen);
 	memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen);
 	sf->hdr.count++;
@@ -282,11 +314,7 @@
 			continue;
 		if (memcmp(sfe->nameval, args->name, args->namelen) != 0)
 			continue;
-		if (((args->flags & ATTR_SECURE) != 0) !=
-		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
-			continue;
-		if (((args->flags & ATTR_ROOT) != 0) !=
-		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
+		if (!xfs_attr_namesp_match(args->flags, sfe->flags))
 			continue;
 		break;
 	}
@@ -363,11 +391,7 @@
 			continue;
 		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
 			continue;
-		if (((args->flags & ATTR_SECURE) != 0) !=
-		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
-			continue;
-		if (((args->flags & ATTR_ROOT) != 0) !=
-		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
+		if (!xfs_attr_namesp_match(args->flags, sfe->flags))
 			continue;
 		return(XFS_ERROR(EEXIST));
 	}
@@ -394,11 +418,7 @@
 			continue;
 		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
 			continue;
-		if (((args->flags & ATTR_SECURE) != 0) !=
-		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
-			continue;
-		if (((args->flags & ATTR_ROOT) != 0) !=
-		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
+		if (!xfs_attr_namesp_match(args->flags, sfe->flags))
 			continue;
 		if (args->flags & ATTR_KERNOVAL) {
 			args->valuelen = sfe->valuelen;
@@ -485,8 +505,7 @@
 		nargs.valuelen = sfe->valuelen;
 		nargs.hashval = xfs_da_hashname((char *)sfe->nameval,
 						sfe->namelen);
-		nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
-				((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
+		nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags);
 		error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */
 		ASSERT(error == ENOATTR);
 		error = xfs_attr_leaf_add(bp, &nargs);
@@ -520,6 +539,10 @@
 	}
 }
 
+
+#define XFS_ISRESET_CURSOR(cursor) \
+	(!((cursor)->initted) && !((cursor)->hashval) && \
+	 !((cursor)->blkno) && !((cursor)->offset))
 /*
  * Copy out entries of shortform attribute lists for attr_list().
  * Shortform attribute lists are not stored in hashval sorted order.
@@ -537,6 +560,7 @@
 	xfs_attr_sf_entry_t *sfe;
 	xfs_inode_t *dp;
 	int sbsize, nsbuf, count, i;
+	int error;
 
 	ASSERT(context != NULL);
 	dp = context->dp;
@@ -552,46 +576,51 @@
 	xfs_attr_trace_l_c("sf start", context);
 
 	/*
-	 * If the buffer is large enough, do not bother with sorting.
+	 * If the buffer is large enough and the cursor is at the start,
+	 * do not bother with sorting since we will return everything in
+	 * one buffer and another call using the cursor won't need to be
+	 * made.
 	 * Note the generous fudge factor of 16 overhead bytes per entry.
+	 * If bufsize is zero then put_listent must be a search function
+	 * and can just scan through what we have.
 	 */
-	if ((dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize) {
+	if (context->bufsize == 0 ||
+	    (XFS_ISRESET_CURSOR(cursor) &&
+             (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
 		for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
 			attrnames_t	*namesp;
 
-			if (((context->flags & ATTR_SECURE) != 0) !=
-			    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
-			    !(context->flags & ATTR_KERNORMALS)) {
+			if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {
 				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 				continue;
 			}
-			if (((context->flags & ATTR_ROOT) != 0) !=
-			    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-			    !(context->flags & ATTR_KERNROOTLS)) {
-				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
-				continue;
-			}
-			namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure:
-				((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-				  &attr_user);
-			if (context->flags & ATTR_KERNOVAL) {
-				ASSERT(context->flags & ATTR_KERNAMELS);
-				context->count += namesp->attr_namelen +
-					sfe->namelen + 1;
-			}
-			else {
-				if (xfs_attr_put_listent(context, namesp,
-						   (char *)sfe->nameval,
-						   (int)sfe->namelen,
-						   (int)sfe->valuelen))
-					break;
-			}
+			namesp = xfs_attr_flags_namesp(sfe->flags);
+			error = context->put_listent(context,
+					   namesp,
+					   (char *)sfe->nameval,
+					   (int)sfe->namelen,
+					   (int)sfe->valuelen,
+					   (char*)&sfe->nameval[sfe->namelen]);
+
+			/*
+			 * Either search callback finished early or
+			 * didn't fit it all in the buffer after all.
+			 */
+			if (context->seen_enough)
+				break;
+
+			if (error)
+				return error;
 			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 		}
 		xfs_attr_trace_l_c("sf big-gulp", context);
 		return(0);
 	}
 
+	/* do no more for a search callback */
+	if (context->bufsize == 0)
+		return 0;
+
 	/*
 	 * It didn't all fit, so we have to sort everything on hashval.
 	 */
@@ -614,15 +643,7 @@
 			kmem_free(sbuf, sbsize);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
-		if (((context->flags & ATTR_SECURE) != 0) !=
-		    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
-		    !(context->flags & ATTR_KERNORMALS)) {
-			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
-			continue;
-		}
-		if (((context->flags & ATTR_ROOT) != 0) !=
-		    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNROOTLS)) {
+		if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {
 			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 			continue;
 		}
@@ -671,24 +692,22 @@
 	for ( ; i < nsbuf; i++, sbp++) {
 		attrnames_t	*namesp;
 
-		namesp = (sbp->flags & XFS_ATTR_SECURE) ? &attr_secure :
-			((sbp->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-			  &attr_user);
+		namesp = xfs_attr_flags_namesp(sbp->flags);
 
 		if (cursor->hashval != sbp->hash) {
 			cursor->hashval = sbp->hash;
 			cursor->offset = 0;
 		}
-		if (context->flags & ATTR_KERNOVAL) {
-			ASSERT(context->flags & ATTR_KERNAMELS);
-			context->count += namesp->attr_namelen +
-						sbp->namelen + 1;
-		} else {
-			if (xfs_attr_put_listent(context, namesp,
-					sbp->name, sbp->namelen,
-					sbp->valuelen))
-				break;
-		}
+		error = context->put_listent(context,
+					namesp,
+					sbp->name,
+					sbp->namelen,
+					sbp->valuelen,
+					&sbp->name[sbp->namelen]);
+		if (error)
+			return error;
+		if (context->seen_enough)
+			break;
 		cursor->offset++;
 	}
 
@@ -810,8 +829,7 @@
 		nargs.value = (char *)&name_loc->nameval[nargs.namelen];
 		nargs.valuelen = be16_to_cpu(name_loc->valuelen);
 		nargs.hashval = be32_to_cpu(entry->hashval);
-		nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
-			      ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
+		nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags);
 		xfs_attr_shortform_add(&nargs, forkoff);
 	}
 	error = 0;
@@ -1098,8 +1116,7 @@
 				     be16_to_cpu(map->size));
 	entry->hashval = cpu_to_be32(args->hashval);
 	entry->flags = tmp ? XFS_ATTR_LOCAL : 0;
-	entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
-			((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
+	entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);
 	if (args->rename) {
 		entry->flags |= XFS_ATTR_INCOMPLETE;
 		if ((args->blkno2 == args->blkno) &&
@@ -1926,7 +1943,7 @@
 		else
 			break;
 	}
-	ASSERT((probe >= 0) && 
+	ASSERT((probe >= 0) &&
 	       (!leaf->hdr.count
 	       || (probe < be16_to_cpu(leaf->hdr.count))));
 	ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval));
@@ -1971,14 +1988,9 @@
 			name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, probe);
 			if (name_loc->namelen != args->namelen)
 				continue;
-			if (memcmp(args->name, (char *)name_loc->nameval,
-					     args->namelen) != 0)
+			if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0)
 				continue;
-			if (((args->flags & ATTR_SECURE) != 0) !=
-			    ((entry->flags & XFS_ATTR_SECURE) != 0))
-				continue;
-			if (((args->flags & ATTR_ROOT) != 0) !=
-			    ((entry->flags & XFS_ATTR_ROOT) != 0))
+			if (!xfs_attr_namesp_match(args->flags, entry->flags))
 				continue;
 			args->index = probe;
 			return(XFS_ERROR(EEXIST));
@@ -1989,11 +2001,7 @@
 			if (memcmp(args->name, (char *)name_rmt->name,
 					     args->namelen) != 0)
 				continue;
-			if (((args->flags & ATTR_SECURE) != 0) !=
-			    ((entry->flags & XFS_ATTR_SECURE) != 0))
-				continue;
-			if (((args->flags & ATTR_ROOT) != 0) !=
-			    ((entry->flags & XFS_ATTR_ROOT) != 0))
+			if (!xfs_attr_namesp_match(args->flags, entry->flags))
 				continue;
 			args->index = probe;
 			args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
@@ -2312,8 +2320,6 @@
 	attrlist_cursor_kern_t *cursor;
 	xfs_attr_leafblock_t *leaf;
 	xfs_attr_leaf_entry_t *entry;
-	xfs_attr_leaf_name_local_t *name_loc;
-	xfs_attr_leaf_name_remote_t *name_rmt;
 	int retval, i;
 
 	ASSERT(bp != NULL);
@@ -2355,9 +2361,8 @@
 	 * We have found our place, start copying out the new attributes.
 	 */
 	retval = 0;
-	for (  ; (i < be16_to_cpu(leaf->hdr.count))
-	     && (retval == 0); entry++, i++) {
-		attrnames_t	*namesp;
+	for (  ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) {
+		attrnames_t *namesp;
 
 		if (be32_to_cpu(entry->hashval) != cursor->hashval) {
 			cursor->hashval = be32_to_cpu(entry->hashval);
@@ -2366,115 +2371,69 @@
 
 		if (entry->flags & XFS_ATTR_INCOMPLETE)
 			continue;		/* skip incomplete entries */
-		if (((context->flags & ATTR_SECURE) != 0) !=
-		    ((entry->flags & XFS_ATTR_SECURE) != 0) &&
-		    !(context->flags & ATTR_KERNORMALS))
-			continue;		/* skip non-matching entries */
-		if (((context->flags & ATTR_ROOT) != 0) !=
-		    ((entry->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNROOTLS))
-			continue;		/* skip non-matching entries */
+		if (!xfs_attr_namesp_match_overrides(context->flags, entry->flags))
+			continue;
 
-		namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
-			((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-			  &attr_user);
+		namesp = xfs_attr_flags_namesp(entry->flags);
 
 		if (entry->flags & XFS_ATTR_LOCAL) {
-			name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
-			if (context->flags & ATTR_KERNOVAL) {
-				ASSERT(context->flags & ATTR_KERNAMELS);
-				context->count += namesp->attr_namelen +
-						(int)name_loc->namelen + 1;
-			} else {
-				retval = xfs_attr_put_listent(context, namesp,
-					(char *)name_loc->nameval,
-					(int)name_loc->namelen,
-					be16_to_cpu(name_loc->valuelen));
-			}
+			xfs_attr_leaf_name_local_t *name_loc =
+				XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
+
+			retval = context->put_listent(context,
+						namesp,
+						(char *)name_loc->nameval,
+						(int)name_loc->namelen,
+						be16_to_cpu(name_loc->valuelen),
+						(char *)&name_loc->nameval[name_loc->namelen]);
+			if (retval)
+				return retval;
 		} else {
-			name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
-			if (context->flags & ATTR_KERNOVAL) {
-				ASSERT(context->flags & ATTR_KERNAMELS);
-				context->count += namesp->attr_namelen +
-						(int)name_rmt->namelen + 1;
-			} else {
-				retval = xfs_attr_put_listent(context, namesp,
-					(char *)name_rmt->name,
-					(int)name_rmt->namelen,
-					be32_to_cpu(name_rmt->valuelen));
+			xfs_attr_leaf_name_remote_t *name_rmt =
+				XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
+
+			int valuelen = be32_to_cpu(name_rmt->valuelen);
+
+			if (context->put_value) {
+				xfs_da_args_t args;
+
+				memset((char *)&args, 0, sizeof(args));
+				args.dp = context->dp;
+				args.whichfork = XFS_ATTR_FORK;
+				args.valuelen = valuelen;
+				args.value = kmem_alloc(valuelen, KM_SLEEP);
+				args.rmtblkno = be32_to_cpu(name_rmt->valueblk);
+				args.rmtblkcnt = XFS_B_TO_FSB(args.dp->i_mount, valuelen);
+				retval = xfs_attr_rmtval_get(&args);
+				if (retval)
+					return retval;
+				retval = context->put_listent(context,
+						namesp,
+						(char *)name_rmt->name,
+						(int)name_rmt->namelen,
+						valuelen,
+						(char*)args.value);
+				kmem_free(args.value, valuelen);
 			}
+			else {
+				retval = context->put_listent(context,
+						namesp,
+						(char *)name_rmt->name,
+						(int)name_rmt->namelen,
+						valuelen,
+						NULL);
+			}
+			if (retval)
+				return retval;
 		}
-		if (retval == 0) {
-			cursor->offset++;
-		}
+		if (context->seen_enough)
+			break;
+		cursor->offset++;
 	}
 	xfs_attr_trace_l_cl("blk end", context, leaf);
 	return(retval);
 }
 
-#define	ATTR_ENTBASESIZE		/* minimum bytes used by an attr */ \
-	(((struct attrlist_ent *) 0)->a_name - (char *) 0)
-#define	ATTR_ENTSIZE(namelen)		/* actual bytes used by an attr */ \
-	((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
-	 & ~(sizeof(u_int32_t)-1))
-
-/*
- * Format an attribute and copy it out to the user's buffer.
- * Take care to check values and protect against them changing later,
- * we may be reading them directly out of a user buffer.
- */
-/*ARGSUSED*/
-STATIC int
-xfs_attr_put_listent(xfs_attr_list_context_t *context,
-		     attrnames_t *namesp, char *name, int namelen, int valuelen)
-{
-	attrlist_ent_t *aep;
-	int arraytop;
-
-	ASSERT(!(context->flags & ATTR_KERNOVAL));
-	if (context->flags & ATTR_KERNAMELS) {
-		char *offset;
-
-		ASSERT(context->count >= 0);
-
-		arraytop = context->count + namesp->attr_namelen + namelen + 1;
-		if (arraytop > context->firstu) {
-			context->count = -1;	/* insufficient space */
-			return(1);
-		}
-		offset = (char *)context->alist + context->count;
-		strncpy(offset, namesp->attr_name, namesp->attr_namelen);
-		offset += namesp->attr_namelen;
-		strncpy(offset, name, namelen);			/* real name */
-		offset += namelen;
-		*offset = '\0';
-		context->count += namesp->attr_namelen + namelen + 1;
-		return(0);
-	}
-
-	ASSERT(context->count >= 0);
-	ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
-	ASSERT(context->firstu >= sizeof(*context->alist));
-	ASSERT(context->firstu <= context->bufsize);
-
-	arraytop = sizeof(*context->alist) +
-			context->count * sizeof(context->alist->al_offset[0]);
-	context->firstu -= ATTR_ENTSIZE(namelen);
-	if (context->firstu < arraytop) {
-		xfs_attr_trace_l_c("buffer full", context);
-		context->alist->al_more = 1;
-		return(1);
-	}
-
-	aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
-	aep->a_valuelen = valuelen;
-	memcpy(aep->a_name, name, namelen);
-	aep->a_name[ namelen ] = 0;
-	context->alist->al_offset[ context->count++ ] = context->firstu;
-	context->alist->al_count = context->count;
-	xfs_attr_trace_l_c("add", context);
-	return(0);
-}
 
 /*========================================================================
  * Manage the INCOMPLETE flag in a leaf entry
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index 51c3ee1..040f732 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -130,6 +130,19 @@
 #define XFS_ATTR_INCOMPLETE	(1 << XFS_ATTR_INCOMPLETE_BIT)
 
 /*
+ * Conversion macros for converting namespace bits from argument flags
+ * to ondisk flags.
+ */
+#define XFS_ATTR_NSP_ARGS_MASK		(ATTR_ROOT | ATTR_SECURE)
+#define XFS_ATTR_NSP_ONDISK_MASK	(XFS_ATTR_ROOT | XFS_ATTR_SECURE)
+#define XFS_ATTR_NSP_ONDISK(flags)	((flags) & XFS_ATTR_NSP_ONDISK_MASK)
+#define XFS_ATTR_NSP_ARGS(flags)	((flags) & XFS_ATTR_NSP_ARGS_MASK)
+#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x)	(((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
+					 ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
+#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x)	(((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
+					 ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
+
+/*
  * Alignment for namelist and valuelist entries (since they are mixed
  * there can be only one alignment value)
  */
@@ -196,16 +209,26 @@
  * Structure used to pass context around among the routines.
  *========================================================================*/
 
+
+struct xfs_attr_list_context;
+
+typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, struct attrnames *,
+				      char *, int, int, char *);
+
 typedef struct xfs_attr_list_context {
-	struct xfs_inode		*dp;	/* inode */
-	struct attrlist_cursor_kern	*cursor;/* position in list */
-	struct attrlist			*alist;	/* output buffer */
-	int				count;	/* num used entries */
-	int				dupcnt;	/* count dup hashvals seen */
-	int				bufsize;/* total buffer size */
-	int				firstu;	/* first used byte in buffer */
-	int				flags;	/* from VOP call */
-	int				resynch;/* T/F: resynch with cursor */
+	struct xfs_inode		*dp;		/* inode */
+	struct attrlist_cursor_kern	*cursor;	/* position in list */
+	struct attrlist			*alist;		/* output buffer */
+	int				seen_enough;	/* T/F: seen enough of list? */
+	int				count;		/* num used entries */
+	int				dupcnt;		/* count dup hashvals seen */
+	int				bufsize;	/* total buffer size */
+	int				firstu;		/* first used byte in buffer */
+	int				flags;		/* from VOP call */
+	int				resynch;	/* T/F: resynch with cursor */
+	int				put_value;	/* T/F: need value for listent */
+	put_listent_func_t		put_listent;	/* list output fmt function */
+	int				index;		/* index into output buffer */
 } xfs_attr_list_context_t;
 
 /*
diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c
index f4fe371..0dc1721 100644
--- a/fs/xfs/xfs_behavior.c
+++ b/fs/xfs/xfs_behavior.c
@@ -110,26 +110,6 @@
 }
 
 /*
- * Look for a specific ops vector on the specified behavior chain.
- * Return the associated behavior descriptor.  Or NULL, if not found.
- */
-bhv_desc_t *
-bhv_lookup(bhv_head_t *bhp, void *ops)
-{
-	bhv_desc_t	*curdesc;
-
-	for (curdesc = bhp->bh_first;
-	     curdesc != NULL;
-	     curdesc = curdesc->bd_next) {
-
-		if (curdesc->bd_ops == ops)
-			return curdesc;
-	}
-
-	return NULL;
-}
-
-/*
  * Looks for the first behavior within a specified range of positions.
  * Return the associated behavior descriptor.  Or NULL, if none found.
  */
diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h
index 6e6e56f..e7ca1fe 100644
--- a/fs/xfs/xfs_behavior.h
+++ b/fs/xfs/xfs_behavior.h
@@ -176,12 +176,10 @@
  * Behavior module prototypes.
  */
 extern void		bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
-extern bhv_desc_t *	bhv_lookup(bhv_head_t *bhp, void *ops);
 extern bhv_desc_t *	bhv_lookup_range(bhv_head_t *bhp, int low, int high);
 extern bhv_desc_t *	bhv_base(bhv_head_t *bhp);
 
 /* No bhv locking on Linux */
-#define bhv_lookup_unlocked	bhv_lookup
 #define bhv_base_unlocked	bhv_base
 
 #endif /* __XFS_BEHAVIOR_H__ */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index bf46fae..5b050c0 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2999,7 +2999,7 @@
 	int			error;	/* error return value */
 	xfs_ifork_t		*ifp;	/* inode fork data */
 	xfs_mount_t		*mp;	/* mount point structure */
-	xfs_bmbt_ptr_t		*pp;	/* ptr to block address */
+	__be64			*pp;	/* ptr to block address */
 	xfs_bmbt_block_t	*rblock;/* root btree block */
 
 	ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -3011,12 +3011,12 @@
 	ASSERT(XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes) == 1);
 	mp = ip->i_mount;
 	pp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, ifp->if_broot_bytes);
+	cbno = be64_to_cpu(*pp);
 	*logflagsp = 0;
 #ifdef DEBUG
-	if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), 1)))
+	if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
 		return error;
 #endif
-	cbno = INT_GET(*pp, ARCH_CONVERT);
 	if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
 			XFS_BMAP_BTREE_REF)))
 		return error;
@@ -3512,9 +3512,9 @@
 	 */
 	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
 	arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
-	INT_SET(kp->br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(arp));
+	kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp));
 	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
-	INT_SET(*pp, ARCH_CONVERT, args.fsbno);
+	*pp = cpu_to_be64(args.fsbno);
 	/*
 	 * Do all this logging at the end so that
 	 * the root is at the right level.
@@ -3705,7 +3705,7 @@
 xfs_bmap_search_extents(
 	xfs_inode_t     *ip,            /* incore inode pointer */
 	xfs_fileoff_t   bno,            /* block number searched for */
-	int             whichfork,      /* data or attr fork */
+	int             fork,      	/* data or attr fork */
 	int             *eofp,          /* out: end of file found */
 	xfs_extnum_t    *lastxp,        /* out: last extent index */
 	xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
@@ -3713,25 +3713,28 @@
 {
 	xfs_ifork_t	*ifp;		/* inode fork pointer */
 	xfs_bmbt_rec_t  *ep;            /* extent record pointer */
-	int		rt;		/* realtime flag    */
 
 	XFS_STATS_INC(xs_look_exlist);
-	ifp = XFS_IFORK_PTR(ip, whichfork);
+	ifp = XFS_IFORK_PTR(ip, fork);
 
 	ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
 
-	rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
-	if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) {
-                cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
-			"start_block : %llx start_off : %llx blkcnt : %llx "
-			"extent-state : %x \n",
-			(ip->i_mount)->m_fsname, (long long)ip->i_ino,
+	if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
+		     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
+		xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+				"Access to block zero in inode %llu "
+				"start_block: %llx start_off: %llx "
+				"blkcnt: %llx extent-state: %x lastx: %x\n",
+			(unsigned long long)ip->i_ino,
 			(unsigned long long)gotp->br_startblock,
 			(unsigned long long)gotp->br_startoff,
 			(unsigned long long)gotp->br_blockcount,
-			gotp->br_state);
-        }
-        return ep;
+			gotp->br_state, *lastxp);
+		*lastxp = NULLEXTNUM;
+		*eofp = 1;
+		return NULL;
+	}
+	return ep;
 }
 
 
@@ -4494,7 +4497,7 @@
 	xfs_ifork_t		*ifp;	/* fork structure */
 	int			level;	/* btree level, for checking */
 	xfs_mount_t		*mp;	/* file system mount structure */
-	xfs_bmbt_ptr_t		*pp;	/* pointer to block address */
+	__be64			*pp;	/* pointer to block address */
 	/* REFERENCED */
 	xfs_extnum_t		room;	/* number of entries there's room for */
 
@@ -4510,10 +4513,10 @@
 	level = be16_to_cpu(block->bb_level);
 	ASSERT(level > 0);
 	pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
-	ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
-	ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
-	ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
-	bno = INT_GET(*pp, ARCH_CONVERT);
+	bno = be64_to_cpu(*pp);
+	ASSERT(bno != NULLDFSBNO);
+	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
 	/*
 	 * Go down the tree until leaf level is reached, following the first
 	 * pointer (leftmost) at each level.
@@ -4530,10 +4533,8 @@
 			break;
 		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
 			1, mp->m_bmap_dmxr[1]);
-		XFS_WANT_CORRUPTED_GOTO(
-			XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)),
-			error0);
-		bno = INT_GET(*pp, ARCH_CONVERT);
+		bno = be64_to_cpu(*pp);
+		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
 		xfs_trans_brelse(tp, bp);
 	}
 	/*
@@ -6141,7 +6142,7 @@
 	short			sz)
 {
 	int			i, j, dmxr;
-	xfs_bmbt_ptr_t		*pp, *thispa;	/* pointer to block address */
+	__be64			*pp, *thispa;	/* pointer to block address */
 	xfs_bmbt_key_t		*prevp, *keyp;
 
 	ASSERT(be16_to_cpu(block->bb_level) > 0);
@@ -6179,11 +6180,10 @@
 				thispa = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
 					xfs_bmbt, block, j, dmxr);
 			}
-			if (INT_GET(*thispa, ARCH_CONVERT) ==
-			    INT_GET(*pp, ARCH_CONVERT)) {
+			if (*thispa == *pp) {
 				cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
 					__FUNCTION__, j, i,
-					INT_GET(*thispa, ARCH_CONVERT));
+					(unsigned long long)be64_to_cpu(*thispa));
 				panic("%s: ptrs are equal in node\n",
 					__FUNCTION__);
 			}
@@ -6210,7 +6210,7 @@
 	xfs_ifork_t		*ifp;	/* fork structure */
 	int			level;	/* btree level, for checking */
 	xfs_mount_t		*mp;	/* file system mount structure */
-	xfs_bmbt_ptr_t		*pp;	/* pointer to block address */
+	__be64			*pp;	/* pointer to block address */
 	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
 	xfs_bmbt_rec_t		*lastp; /* pointer to previous extent */
 	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
@@ -6231,10 +6231,12 @@
 	ASSERT(level > 0);
 	xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
 	pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
-	ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
-	ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
-	ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
-	bno = INT_GET(*pp, ARCH_CONVERT);
+	bno = be64_to_cpu(*pp);
+
+	ASSERT(bno != NULLDFSBNO);
+	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
+
 	/*
 	 * Go down the tree until leaf level is reached, following the first
 	 * pointer (leftmost) at each level.
@@ -6265,8 +6267,8 @@
 		xfs_check_block(block, mp, 0, 0);
 		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
 			1, mp->m_bmap_dmxr[1]);
-		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)), error0);
-		bno = INT_GET(*pp, ARCH_CONVERT);
+		bno = be64_to_cpu(*pp);
+		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
 		if (bp_release) {
 			bp_release = 0;
 			xfs_trans_brelse(NULL, bp);
@@ -6372,7 +6374,7 @@
 	xfs_ifork_t		*ifp;	/* fork structure */
 	int			level;	/* btree level, for checking */
 	xfs_mount_t		*mp;	/* file system mount structure */
-	xfs_bmbt_ptr_t		*pp;	/* pointer to block address */
+	__be64			*pp;	/* pointer to block address */
 
 	bno = NULLFSBLOCK;
 	mp = ip->i_mount;
@@ -6395,10 +6397,10 @@
 	level = be16_to_cpu(block->bb_level);
 	ASSERT(level > 0);
 	pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
-	ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
-	ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
-	ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
-	bno = INT_GET(*pp, ARCH_CONVERT);
+	bno = be64_to_cpu(*pp);
+	ASSERT(bno != NULLDFSBNO);
+	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
 
 	if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
 		XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
@@ -6425,7 +6427,7 @@
 	int			error;
 	xfs_buf_t		*bp, *nbp;
 	int			level = levelin;
-	xfs_bmbt_ptr_t          *pp;
+	__be64			*pp;
 	xfs_fsblock_t           bno = blockno;
 	xfs_fsblock_t		nextbno;
 	xfs_bmbt_block_t        *block, *nextblock;
@@ -6452,7 +6454,7 @@
 		/* Dive to the next level */
 		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
 			xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
-		bno = INT_GET(*pp, ARCH_CONVERT);
+		bno = be64_to_cpu(*pp);
 		if (unlikely((error =
 		     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
 			xfs_trans_brelse(tp, bp);
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 18fb738..a7b835b 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -58,7 +58,7 @@
 STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *);
 STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *);
 STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *,
-		xfs_bmbt_key_t *, xfs_btree_cur_t **, int *);
+		__uint64_t *, xfs_btree_cur_t **, int *);
 STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int);
 
 
@@ -192,16 +192,11 @@
 	xfs_btree_cur_t		*cur,
 	int			i,
 	xfs_fsblock_t		f,
-	xfs_bmbt_key_t		*k,
+	xfs_dfiloff_t		o,
 	int			line)
 {
-	xfs_dfsbno_t		d;
-	xfs_dfiloff_t		o;
-
-	d = (xfs_dfsbno_t)f;
-	o = INT_GET(k->br_startoff, ARCH_CONVERT);
 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
-		i, d >> 32, (int)d, o >> 32,
+		i, (xfs_dfsbno_t)f >> 32, (int)f, o >> 32,
 		(int)o, 0, 0, 0,
 		0, 0, 0);
 }
@@ -248,7 +243,7 @@
 {
 	xfs_dfiloff_t		o;
 
-	o = INT_GET(k->br_startoff, ARCH_CONVERT);
+	o = be64_to_cpu(k->br_startoff);
 	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
 		i, o >> 32, (int)o, 0,
 		0, 0, 0, 0,
@@ -286,8 +281,8 @@
 	xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
 #define	XFS_BMBT_TRACE_ARGI(c,i)	\
 	xfs_bmbt_trace_argi(fname, c, i, __LINE__)
-#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)	\
-	xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__)
+#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,s)	\
+	xfs_bmbt_trace_argifk(fname, c, i, f, s, __LINE__)
 #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)	\
 	xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
 #define	XFS_BMBT_TRACE_ARGIK(c,i,k)	\
@@ -299,7 +294,7 @@
 #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)
 #define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
 #define	XFS_BMBT_TRACE_ARGI(c,i)
-#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)
+#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,s)
 #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
 #define	XFS_BMBT_TRACE_ARGIK(c,i,k)
 #define	XFS_BMBT_TRACE_CURSOR(c,s)
@@ -357,7 +352,7 @@
 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
 	XFS_BMBT_TRACE_ARGI(cur, level);
 	ptr = cur->bc_ptrs[level];
-	tcur = (xfs_btree_cur_t *)0;
+	tcur = NULL;
 	if (ptr == 0) {
 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
 		*stat = 0;
@@ -382,7 +377,7 @@
 		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
 #ifdef DEBUG
 		for (i = ptr; i < numrecs; i++) {
-			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
+			if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) {
 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 				goto error0;
 			}
@@ -404,7 +399,8 @@
 			xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1);
 		}
 		if (ptr == 1) {
-			INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp));
+			key.br_startoff =
+				cpu_to_be64(xfs_bmbt_disk_get_startoff(rp));
 			kp = &key;
 		}
 	}
@@ -621,7 +617,7 @@
 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
 		for (i = 0; i < numrrecs; i++) {
-			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
+			if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) {
 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 				goto error0;
 			}
@@ -748,7 +744,7 @@
 	int			logflags;	/* inode logging flags */
 	xfs_fsblock_t		nbno;		/* new block number */
 	struct xfs_btree_cur	*ncur;		/* new btree cursor */
-	xfs_bmbt_key_t		nkey;		/* new btree key value */
+	__uint64_t		startoff;	/* new btree key value */
 	xfs_bmbt_rec_t		nrec;		/* new record count */
 	int			optr;		/* old key/record index */
 	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
@@ -759,9 +755,8 @@
 	ASSERT(level < cur->bc_nlevels);
 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
 	XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);
-	ncur = (xfs_btree_cur_t *)0;
-	INT_SET(key.br_startoff, ARCH_CONVERT,
-		xfs_bmbt_disk_get_startoff(recp));
+	ncur = NULL;
+	key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp));
 	optr = ptr = cur->bc_ptrs[level];
 	if (ptr == 0) {
 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
@@ -820,7 +815,7 @@
 					optr = ptr = cur->bc_ptrs[level];
 				} else {
 					if ((error = xfs_bmbt_split(cur, level,
-							&nbno, &nkey, &ncur,
+							&nbno, &startoff, &ncur,
 							&i))) {
 						XFS_BMBT_TRACE_CURSOR(cur,
 							ERROR);
@@ -840,7 +835,7 @@
 #endif
 						ptr = cur->bc_ptrs[level];
 						xfs_bmbt_disk_set_allf(&nrec,
-							nkey.br_startoff, 0, 0,
+							startoff, 0, 0,
 							XFS_EXT_NORM);
 					} else {
 						XFS_BMBT_TRACE_CURSOR(cur,
@@ -858,7 +853,7 @@
 		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
 #ifdef DEBUG
 		for (i = numrecs; i >= ptr; i--) {
-			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT),
+			if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1],
 					level))) {
 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 				return error;
@@ -870,14 +865,13 @@
 		memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
 			(numrecs - ptr + 1) * sizeof(*pp));
 #ifdef DEBUG
-		if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop,
-				level))) {
+		if ((error = xfs_btree_check_lptr(cur, *bnop, level))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			return error;
 		}
 #endif
 		kp[ptr - 1] = key;
-		INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
+		pp[ptr - 1] = cpu_to_be64(*bnop);
 		numrecs++;
 		block->bb_numrecs = cpu_to_be16(numrecs);
 		xfs_bmbt_log_keys(cur, bp, ptr, numrecs);
@@ -988,7 +982,7 @@
 	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
 #ifdef DEBUG
 	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
-		if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) {
+		if ((error = xfs_btree_check_lptr_disk(cur, cpp[i], level - 1))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			return error;
 		}
@@ -1132,7 +1126,7 @@
 			d = XFS_FSB_TO_DADDR(mp, fsbno);
 			bp = cur->bc_bufs[level];
 			if (bp && XFS_BUF_ADDR(bp) != d)
-				bp = (xfs_buf_t *)0;
+				bp = NULL;
 			if (!bp) {
 				if ((error = xfs_btree_read_bufl(mp, tp, fsbno,
 						0, &bp, XFS_BMAP_BTREE_REF))) {
@@ -1170,7 +1164,7 @@
 				keyno = (low + high) >> 1;
 				if (level > 0) {
 					kkp = kkbase + keyno - 1;
-					startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT);
+					startoff = be64_to_cpu(kkp->br_startoff);
 				} else {
 					krp = krbase + keyno - 1;
 					startoff = xfs_bmbt_disk_get_startoff(krp);
@@ -1189,13 +1183,13 @@
 			if (diff > 0 && --keyno < 1)
 				keyno = 1;
 			pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);
+			fsbno = be64_to_cpu(*pp);
 #ifdef DEBUG
-			if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
+			if ((error = xfs_btree_check_lptr(cur, fsbno, level))) {
 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 				return error;
 			}
 #endif
-			fsbno = INT_GET(*pp, ARCH_CONVERT);
 			cur->bc_ptrs[level] = keyno;
 		}
 	}
@@ -1313,7 +1307,7 @@
 		lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur);
 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
-		if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) {
+		if ((error = xfs_btree_check_lptr_disk(cur, *rpp, level))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			return error;
 		}
@@ -1340,7 +1334,7 @@
 	if (level > 0) {
 #ifdef DEBUG
 		for (i = 0; i < rrecs; i++) {
-			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
+			if ((error = xfs_btree_check_lptr_disk(cur, rpp[i + 1],
 					level))) {
 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 				return error;
@@ -1354,8 +1348,7 @@
 	} else {
 		memmove(rrp, rrp + 1, rrecs * sizeof(*rrp));
 		xfs_bmbt_log_recs(cur, rbp, 1, rrecs);
-		INT_SET(key.br_startoff, ARCH_CONVERT,
-			xfs_bmbt_disk_get_startoff(rrp));
+		key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp));
 		rkp = &key;
 	}
 	if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) {
@@ -1445,7 +1438,7 @@
 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
 		for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
-			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
+			if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) {
 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 				return error;
 			}
@@ -1454,7 +1447,7 @@
 		memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
 		memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
 #ifdef DEBUG
-		if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) {
+		if ((error = xfs_btree_check_lptr_disk(cur, *lpp, level))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			return error;
 		}
@@ -1469,8 +1462,7 @@
 		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
 		*rrp = *lrp;
 		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
-		INT_SET(key.br_startoff, ARCH_CONVERT,
-			xfs_bmbt_disk_get_startoff(rrp));
+		key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp));
 		rkp = &key;
 	}
 	be16_add(&left->bb_numrecs, -1);
@@ -1535,7 +1527,7 @@
 	xfs_btree_cur_t		*cur,
 	int			level,
 	xfs_fsblock_t		*bnop,
-	xfs_bmbt_key_t		*keyp,
+	__uint64_t		*startoff,
 	xfs_btree_cur_t		**curp,
 	int			*stat)		/* success/failure */
 {
@@ -1560,7 +1552,7 @@
 	xfs_bmbt_rec_t		*rrp;		/* right record pointer */
 
 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
-	XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp);
+	XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff);
 	args.tp = cur->bc_tp;
 	args.mp = cur->bc_mp;
 	lbp = cur->bc_bufs[level];
@@ -1619,7 +1611,7 @@
 		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
 		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
-			if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) {
+			if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) {
 				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 				return error;
 			}
@@ -1629,13 +1621,13 @@
 		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
 		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
 		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-		keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT);
+		*startoff = be64_to_cpu(rkp->br_startoff);
 	} else {
 		lrp = XFS_BMAP_REC_IADDR(left, i, cur);
 		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
 		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
 		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-		keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp);
+		*startoff = xfs_bmbt_disk_get_startoff(rrp);
 	}
 	be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
 	right->bb_rightsib = left->bb_rightsib;
@@ -1728,9 +1720,9 @@
 {
 	int			dmxr;
 	xfs_bmbt_key_t		*fkp;
-	xfs_bmbt_ptr_t		*fpp;
+	__be64			*fpp;
 	xfs_bmbt_key_t		*tkp;
-	xfs_bmbt_ptr_t		*tpp;
+	__be64			*tpp;
 
 	rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
 	rblock->bb_level = dblock->bb_level;
@@ -1745,7 +1737,7 @@
 	tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
 	dmxr = be16_to_cpu(dblock->bb_numrecs);
 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
-	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
+	memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
 }
 
 /*
@@ -1805,7 +1797,7 @@
 	tp = cur->bc_tp;
 	mp = cur->bc_mp;
 	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
-		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
+		fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur));
 		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
 				XFS_BMAP_BTREE_REF))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
@@ -2135,7 +2127,7 @@
 	tp = cur->bc_tp;
 	mp = cur->bc_mp;
 	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
-		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
+		fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur));
 		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
 				XFS_BMAP_BTREE_REF))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
@@ -2178,7 +2170,7 @@
 	level = 0;
 	nbno = NULLFSBLOCK;
 	xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
-	ncur = (xfs_btree_cur_t *)0;
+	ncur = NULL;
 	pcur = cur;
 	do {
 		if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur,
@@ -2205,7 +2197,7 @@
 		}
 		if (ncur) {
 			pcur = ncur;
-			ncur = (xfs_btree_cur_t *)0;
+			ncur = NULL;
 		}
 	} while (nbno != NULLFSBLOCK);
 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
@@ -2356,12 +2348,12 @@
 	args.firstblock = args.fsbno;
 	if (args.fsbno == NULLFSBLOCK) {
 #ifdef DEBUG
-		if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
+		if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			return error;
 		}
 #endif
-		args.fsbno = INT_GET(*pp, ARCH_CONVERT);
+		args.fsbno = be64_to_cpu(*pp);
 		args.type = XFS_ALLOCTYPE_START_BNO;
 	} else
 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -2393,7 +2385,7 @@
 	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
 #ifdef DEBUG
 	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
-		if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
+		if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) {
 			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 			return error;
 		}
@@ -2401,13 +2393,12 @@
 #endif
 	memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));
 #ifdef DEBUG
-	if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)args.fsbno,
-			level))) {
+	if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) {
 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 		return error;
 	}
 #endif
-	INT_SET(*pp, ARCH_CONVERT, args.fsbno);
+	*pp = cpu_to_be64(args.fsbno);
 	xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs),
 		cur->bc_private.b.whichfork);
 	xfs_btree_setbuf(cur, level, bp);
@@ -2681,9 +2672,9 @@
 {
 	int			dmxr;
 	xfs_bmbt_key_t		*fkp;
-	xfs_bmbt_ptr_t		*fpp;
+	__be64			*fpp;
 	xfs_bmbt_key_t		*tkp;
-	xfs_bmbt_ptr_t		*tpp;
+	__be64			*tpp;
 
 	ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
 	ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO);
@@ -2698,7 +2689,7 @@
 	tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
 	dmxr = be16_to_cpu(dblock->bb_numrecs);
 	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
-	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
+	memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
 }
 
 /*
@@ -2740,7 +2731,7 @@
 		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
 		return 0;
 	}
-	INT_SET(key.br_startoff, ARCH_CONVERT, off);
+	key.br_startoff = cpu_to_be64(off);
 	if ((error = xfs_bmbt_updkey(cur, &key, 1))) {
 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
 		return error;
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 6478cfa..49539de 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -163,13 +163,14 @@
 /*
  * Key structure for non-leaf levels of the tree.
  */
-typedef struct xfs_bmbt_key
-{
-	xfs_dfiloff_t	br_startoff;	/* starting file offset */
+typedef struct xfs_bmbt_key {
+	__be64		br_startoff;	/* starting file offset */
 } xfs_bmbt_key_t, xfs_bmdr_key_t;
 
-typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;	/* btree pointer type */
-					/* btree block header type */
+/* btree pointer type */
+typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
+
+/* btree block header type */
 typedef struct xfs_btree_lblock xfs_bmbt_block_t;
 
 #define XFS_BUF_TO_BMBT_BLOCK(bp)	((xfs_bmbt_block_t *)XFS_BUF_PTR(bp))
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index ee2255b..aeb87ca 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -161,7 +161,7 @@
 
 		k1 = ak1;
 		k2 = ak2;
-		ASSERT(INT_GET(k1->br_startoff, ARCH_CONVERT) < INT_GET(k2->br_startoff, ARCH_CONVERT));
+		ASSERT(be64_to_cpu(k1->br_startoff) < be64_to_cpu(k2->br_startoff));
 		break;
 	    }
 	case XFS_BTNUM_INO: {
@@ -170,7 +170,7 @@
 
 		k1 = ak1;
 		k2 = ak2;
-		ASSERT(INT_GET(k1->ir_startino, ARCH_CONVERT) < INT_GET(k2->ir_startino, ARCH_CONVERT));
+		ASSERT(be32_to_cpu(k1->ir_startino) < be32_to_cpu(k2->ir_startino));
 		break;
 	    }
 	default:
@@ -285,8 +285,8 @@
 
 		r1 = ar1;
 		r2 = ar2;
-		ASSERT(INT_GET(r1->ir_startino, ARCH_CONVERT) + XFS_INODES_PER_CHUNK <=
-		       INT_GET(r2->ir_startino, ARCH_CONVERT));
+		ASSERT(be32_to_cpu(r1->ir_startino) + XFS_INODES_PER_CHUNK <=
+		       be32_to_cpu(r2->ir_startino));
 		break;
 	    }
 	default:
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 44f1bd9..892b06c 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -145,7 +145,7 @@
 	union {
 		xfs_alloc_rec_incore_t	a;
 		xfs_bmbt_irec_t		b;
-		xfs_inobt_rec_t		i;
+		xfs_inobt_rec_incore_t	i;
 	}		bc_rec;		/* current insert/search record value */
 	struct xfs_buf	*bc_bufs[XFS_BTREE_MAXLEVELS];	/* buf ptr per level */
 	int		bc_ptrs[XFS_BTREE_MAXLEVELS];	/* key/record # */
@@ -243,6 +243,9 @@
 	xfs_dfsbno_t		ptr,	/* btree block disk address */
 	int			level);	/* btree block level */
 
+#define xfs_btree_check_lptr_disk(cur, ptr, level) \
+	xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level)
+
 /*
  * Checking routine: check that short form block header is ok.
  */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index a4aa539..7a55c24 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -234,7 +234,6 @@
 	ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
 	       (bip->bli_flags & XFS_BLI_STALE));
 	bp = bip->bli_buf;
-	ASSERT(XFS_BUF_BP_ISMAPPED(bp));
 	vecp = log_vector;
 
 	/*
@@ -628,25 +627,6 @@
 }
 
 /*
- * This is called when the transaction holding the buffer is aborted.
- * Just behave as if the transaction had been cancelled. If we're shutting down
- * and have aborted this transaction, we'll trap this buffer when it tries to
- * get written out.
- */
-STATIC void
-xfs_buf_item_abort(
-	xfs_buf_log_item_t	*bip)
-{
-	xfs_buf_t	*bp;
-
-	bp = bip->bli_buf;
-	xfs_buftrace("XFS_ABORT", bp);
-	XFS_BUF_SUPER_STALE(bp);
-	xfs_buf_item_unlock(bip);
-	return;
-}
-
-/*
  * This is called to asynchronously write the buffer associated with this
  * buf log item out to disk. The buffer will already have been locked by
  * a successful call to xfs_buf_item_trylock().  If the buffer still has
@@ -693,7 +673,6 @@
 	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_buf_item_committed,
 	.iop_push	= (void(*)(xfs_log_item_t*))xfs_buf_item_push,
-	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_buf_item_abort,
 	.iop_pushbuf	= NULL,
 	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_buf_item_committing
@@ -901,7 +880,6 @@
 	XFS_BUF_SET_FSPRIVATE(bp, bip->bli_item.li_bio_list);
 	if ((XFS_BUF_FSPRIVATE(bp, void *) == NULL) &&
 	    (XFS_BUF_IODONE_FUNC(bp) != NULL)) {
-		ASSERT((XFS_BUF_ISUNINITIAL(bp)) == 0);
 		XFS_BUF_CLR_IODONE_FUNC(bp);
 	}
 
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 32ab61d..a68bc1f1 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -1054,7 +1054,7 @@
 	xfs_da_node_entry_t *btree;
 	xfs_dablk_t blkno;
 	int probe, span, max, error, retval;
-	xfs_dahash_t hashval;
+	xfs_dahash_t hashval, btreehashval;
 	xfs_da_args_t *args;
 
 	args = state->args;
@@ -1079,30 +1079,32 @@
 			return(error);
 		}
 		curr = blk->bp->data;
-		ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC ||
-		       be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC ||
-		       be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC);
+		blk->magic = be16_to_cpu(curr->magic);
+		ASSERT(blk->magic == XFS_DA_NODE_MAGIC ||
+		       blk->magic == XFS_DIR2_LEAFN_MAGIC ||
+		       blk->magic == XFS_ATTR_LEAF_MAGIC);
 
 		/*
 		 * Search an intermediate node for a match.
 		 */
-		blk->magic = be16_to_cpu(curr->magic);
 		if (blk->magic == XFS_DA_NODE_MAGIC) {
 			node = blk->bp->data;
-			blk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval);
+			max = be16_to_cpu(node->hdr.count);
+			btreehashval = node->btree[max-1].hashval;
+			blk->hashval = be32_to_cpu(btreehashval);
 
 			/*
 			 * Binary search.  (note: small blocks will skip loop)
 			 */
-			max = be16_to_cpu(node->hdr.count);
 			probe = span = max / 2;
 			hashval = args->hashval;
 			for (btree = &node->btree[probe]; span > 4;
 				   btree = &node->btree[probe]) {
 				span /= 2;
-				if (be32_to_cpu(btree->hashval) < hashval)
+				btreehashval = be32_to_cpu(btree->hashval);
+				if (btreehashval < hashval)
 					probe += span;
-				else if (be32_to_cpu(btree->hashval) > hashval)
+				else if (btreehashval > hashval)
 					probe -= span;
 				else
 					break;
@@ -1133,10 +1135,10 @@
 				blk->index = probe;
 				blkno = be32_to_cpu(btree->before);
 			}
-		} else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
+		} else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
 			blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
 			break;
-		} else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
+		} else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
 			blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
 			break;
 		}
@@ -1152,11 +1154,13 @@
 		if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
 			retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
 							&blk->index, state);
-		}
-		else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
+		} else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
 			retval = xfs_attr_leaf_lookup_int(blk->bp, args);
 			blk->index = args->index;
 			args->blkno = blk->blkno;
+		} else {
+			ASSERT(0);
+			return XFS_ERROR(EFSCORRUPTED);
 		}
 		if (((retval == ENOENT) || (retval == ENOATTR)) &&
 		    (blk->hashval == args->hashval)) {
@@ -1166,8 +1170,7 @@
 				return(error);
 			if (retval == 0) {
 				continue;
-			}
-			else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
+			} else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
 				/* path_shift() gives ENOENT */
 				retval = XFS_ERROR(ENOATTR);
 			}
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index bc43163..0893e16 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -18,14 +18,6 @@
 #ifndef	__XFS_ERROR_H__
 #define	__XFS_ERROR_H__
 
-#define XFS_ERECOVER	1	/* Failure to recover log */
-#define XFS_ELOGSTAT	2	/* Failure to stat log in user space */
-#define XFS_ENOLOGSPACE	3	/* Reservation too large */
-#define XFS_ENOTSUP	4	/* Operation not supported */
-#define	XFS_ENOLSN	5	/* Can't find the lsn you asked for */
-#define XFS_ENOTFOUND	6
-#define XFS_ENOTXFS	7	/* Not XFS filesystem */
-
 #ifdef DEBUG
 #define	XFS_ERROR_NTRAP	10
 extern int	xfs_etrap[XFS_ERROR_NTRAP];
@@ -175,6 +167,7 @@
 #define		XFS_PTAG_SHUTDOWN_CORRUPT	0x00000010
 #define		XFS_PTAG_SHUTDOWN_IOERROR	0x00000020
 #define		XFS_PTAG_SHUTDOWN_LOGERROR	0x00000040
+#define		XFS_PTAG_FSBLOCK_ZERO		0x00000080
 
 struct xfs_mount;
 /* PRINTFLIKE4 */
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 6cf6d87..6dba781 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -33,9 +33,6 @@
 kmem_zone_t	*xfs_efd_zone;
 
 STATIC void	xfs_efi_item_unlock(xfs_efi_log_item_t *);
-STATIC void	xfs_efi_item_abort(xfs_efi_log_item_t *);
-STATIC void	xfs_efd_item_abort(xfs_efd_log_item_t *);
-
 
 void
 xfs_efi_item_free(xfs_efi_log_item_t *efip)
@@ -184,7 +181,7 @@
 xfs_efi_item_unlock(xfs_efi_log_item_t *efip)
 {
 	if (efip->efi_item.li_flags & XFS_LI_ABORTED)
-		xfs_efi_item_abort(efip);
+		xfs_efi_item_free(efip);
 	return;
 }
 
@@ -202,18 +199,6 @@
 }
 
 /*
- * This is called when the transaction logging the EFI is aborted.
- * Free up the EFI and return.  No need to clean up the slot for
- * the item in the transaction.  That was done by the unpin code
- * which is called prior to this routine in the abort/fs-shutdown path.
- */
-STATIC void
-xfs_efi_item_abort(xfs_efi_log_item_t *efip)
-{
-	xfs_efi_item_free(efip);
-}
-
-/*
  * There isn't much you can do to push on an efi item.  It is simply
  * stuck waiting for all of its corresponding efd items to be
  * committed to disk.
@@ -255,7 +240,6 @@
 	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_efi_item_committed,
 	.iop_push	= (void(*)(xfs_log_item_t*))xfs_efi_item_push,
-	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_efi_item_abort,
 	.iop_pushbuf	= NULL,
 	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_efi_item_committing
@@ -386,33 +370,6 @@
 	}
 }
 
-/*
- * This is called when the transaction that should be committing the
- * EFD corresponding to the given EFI is aborted.  The committed and
- * canceled flags are used to coordinate the freeing of the EFI and
- * the references by the transaction that committed it.
- */
-STATIC void
-xfs_efi_cancel(
-	xfs_efi_log_item_t	*efip)
-{
-	xfs_mount_t	*mp;
-	SPLDECL(s);
-
-	mp = efip->efi_item.li_mountp;
-	AIL_LOCK(mp, s);
-	if (efip->efi_flags & XFS_EFI_COMMITTED) {
-		/*
-		 * xfs_trans_delete_ail() drops the AIL lock.
-		 */
-		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-		xfs_efi_item_free(efip);
-	} else {
-		efip->efi_flags |= XFS_EFI_CANCELED;
-		AIL_UNLOCK(mp, s);
-	}
-}
-
 STATIC void
 xfs_efd_item_free(xfs_efd_log_item_t *efdp)
 {
@@ -514,7 +471,7 @@
 xfs_efd_item_unlock(xfs_efd_log_item_t *efdp)
 {
 	if (efdp->efd_item.li_flags & XFS_LI_ABORTED)
-		xfs_efd_item_abort(efdp);
+		xfs_efd_item_free(efdp);
 	return;
 }
 
@@ -541,27 +498,6 @@
 }
 
 /*
- * The transaction of which this EFD is a part has been aborted.
- * Inform its companion EFI of this fact and then clean up after
- * ourselves.  No need to clean up the slot for the item in the
- * transaction.  That was done by the unpin code which is called
- * prior to this routine in the abort/fs-shutdown path.
- */
-STATIC void
-xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
-{
-	/*
-	 * If we got a log I/O error, it's always the case that the LR with the
-	 * EFI got unpinned and freed before the EFD got aborted. So don't
-	 * reference the EFI at all in that case.
-	 */
-	if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
-		xfs_efi_cancel(efdp->efd_efip);
-
-	xfs_efd_item_free(efdp);
-}
-
-/*
  * There isn't much you can do to push on an efd item.  It is simply
  * stuck waiting for the log to be flushed to disk.
  */
@@ -602,7 +538,6 @@
 	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_efd_item_committed,
 	.iop_push	= (void(*)(xfs_log_item_t*))xfs_efd_item_push,
-	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_efd_item_abort,
 	.iop_pushbuf	= NULL,
 	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_efd_item_committing
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 0ea45ed..2f049f6 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -33,14 +33,16 @@
  * conversion routine.
  */
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_extent_32 {
-	xfs_dfsbno_t	ext_start;
-	xfs_extlen_t	ext_len;
+	__uint64_t	ext_start;
+	__uint32_t	ext_len;
 } __attribute__((packed)) xfs_extent_32_t;
+#endif
 
 typedef struct xfs_extent_64 {
-	xfs_dfsbno_t	ext_start;
-	xfs_extlen_t	ext_len;
+	__uint64_t	ext_start;
+	__uint32_t	ext_len;
 	__uint32_t	ext_pad;
 } xfs_extent_64_t;
 
@@ -50,25 +52,27 @@
  * size is given by efi_nextents.
  */
 typedef struct xfs_efi_log_format {
-	unsigned short		efi_type;	/* efi log item type */
-	unsigned short		efi_size;	/* size of this item */
-	uint			efi_nextents;	/* # extents to free */
+	__uint16_t		efi_type;	/* efi log item type */
+	__uint16_t		efi_size;	/* size of this item */
+	__uint32_t		efi_nextents;	/* # extents to free */
 	__uint64_t		efi_id;		/* efi identifier */
 	xfs_extent_t		efi_extents[1];	/* array of extents to free */
 } xfs_efi_log_format_t;
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_efi_log_format_32 {
-	unsigned short		efi_type;	/* efi log item type */
-	unsigned short		efi_size;	/* size of this item */
-	uint			efi_nextents;	/* # extents to free */
+	__uint16_t		efi_type;	/* efi log item type */
+	__uint16_t		efi_size;	/* size of this item */
+	__uint32_t		efi_nextents;	/* # extents to free */
 	__uint64_t		efi_id;		/* efi identifier */
 	xfs_extent_32_t		efi_extents[1];	/* array of extents to free */
 } __attribute__((packed)) xfs_efi_log_format_32_t;
+#endif
 
 typedef struct xfs_efi_log_format_64 {
-	unsigned short		efi_type;	/* efi log item type */
-	unsigned short		efi_size;	/* size of this item */
-	uint			efi_nextents;	/* # extents to free */
+	__uint16_t		efi_type;	/* efi log item type */
+	__uint16_t		efi_size;	/* size of this item */
+	__uint32_t		efi_nextents;	/* # extents to free */
 	__uint64_t		efi_id;		/* efi identifier */
 	xfs_extent_64_t		efi_extents[1];	/* array of extents to free */
 } xfs_efi_log_format_64_t;
@@ -79,25 +83,27 @@
  * size is given by efd_nextents;
  */
 typedef struct xfs_efd_log_format {
-	unsigned short		efd_type;	/* efd log item type */
-	unsigned short		efd_size;	/* size of this item */
-	uint			efd_nextents;	/* # of extents freed */
+	__uint16_t		efd_type;	/* efd log item type */
+	__uint16_t		efd_size;	/* size of this item */
+	__uint32_t		efd_nextents;	/* # of extents freed */
 	__uint64_t		efd_efi_id;	/* id of corresponding efi */
 	xfs_extent_t		efd_extents[1];	/* array of extents freed */
 } xfs_efd_log_format_t;
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_efd_log_format_32 {
-	unsigned short		efd_type;	/* efd log item type */
-	unsigned short		efd_size;	/* size of this item */
-	uint			efd_nextents;	/* # of extents freed */
+	__uint16_t		efd_type;	/* efd log item type */
+	__uint16_t		efd_size;	/* size of this item */
+	__uint32_t		efd_nextents;	/* # of extents freed */
 	__uint64_t		efd_efi_id;	/* id of corresponding efi */
 	xfs_extent_32_t		efd_extents[1];	/* array of extents freed */
 } __attribute__((packed)) xfs_efd_log_format_32_t;
+#endif
 
 typedef struct xfs_efd_log_format_64 {
-	unsigned short		efd_type;	/* efd log item type */
-	unsigned short		efd_size;	/* size of this item */
-	uint			efd_nextents;	/* # of extents freed */
+	__uint16_t		efd_type;	/* efd log item type */
+	__uint16_t		efd_size;	/* size of this item */
+	__uint32_t		efd_nextents;	/* # of extents freed */
 	__uint64_t		efd_efi_id;	/* id of corresponding efi */
 	xfs_extent_64_t		efd_extents[1];	/* array of extents freed */
 } xfs_efd_log_format_64_t;
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 0f0ad15..1335449 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -22,8 +22,6 @@
  * SGI's XFS filesystem's major stuff (constants, structures)
  */
 
-#define XFS_NAME	"xfs"
-
 /*
  * Direct I/O attribute record used with XFS_IOC_DIOINFO
  * d_miniosz is the min xfer size, xfer size multiple and file seek offset
@@ -426,11 +424,7 @@
 				 - (char *) &(handle))			  \
 				 + (handle).ha_fid.xfs_fid_len)
 
-#define XFS_HANDLE_CMP(h1, h2)	memcmp(h1, h2, sizeof(xfs_handle_t))
-
-#define FSHSIZE		sizeof(fsid_t)
-
-/* 
+/*
  * Flags for going down operation
  */
 #define XFS_FSOP_GOING_FLAGS_DEFAULT		0x0	/* going down */
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 33164a8..a446e5a 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -458,7 +458,7 @@
 		 */
 		if (XFS_FORCED_SHUTDOWN(mp)) {
 			up_read(&mp->m_peraglock);
-			return (xfs_buf_t *)0;
+			return NULL;
 		}
 		agno++;
 		if (agno >= agcount)
@@ -466,7 +466,7 @@
 		if (agno == pagno) {
 			if (flags == 0) {
 				up_read(&mp->m_peraglock);
-				return (xfs_buf_t *)0;
+				return NULL;
 			}
 			flags = 0;
 		}
@@ -529,10 +529,10 @@
 	int		offset;		/* index of inode in chunk */
 	xfs_agino_t	pagino;		/* parent's a.g. relative inode # */
 	xfs_agnumber_t	pagno;		/* parent's allocation group number */
-	xfs_inobt_rec_t	rec;		/* inode allocation record */
+	xfs_inobt_rec_incore_t rec;	/* inode allocation record */
 	xfs_agnumber_t	tagno;		/* testing allocation group number */
 	xfs_btree_cur_t	*tcur;		/* temp cursor */
-	xfs_inobt_rec_t	trec;		/* temp inode allocation record */
+	xfs_inobt_rec_incore_t trec;	/* temp inode allocation record */
 
 
 	if (*IO_agbp == NULL) {
@@ -945,7 +945,7 @@
 	int		ilen;	/* inodes in an inode cluster */
 	xfs_mount_t	*mp;	/* mount structure for filesystem */
 	int		off;	/* offset of inode in inode chunk */
-	xfs_inobt_rec_t	rec;	/* btree record */
+	xfs_inobt_rec_incore_t rec;	/* btree record */
 
 	mp = tp->t_mountp;
 
@@ -1195,6 +1195,7 @@
 					"(0x%llx)",
 					ino, XFS_AGINO_TO_INO(mp, agno, agino));
 		}
+		xfs_stack_trace();
 #endif /* DEBUG */
 		return XFS_ERROR(EINVAL);
 	}
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 616eeeb..8cdeeaf 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -568,7 +568,7 @@
 	/*
 	 * Make a key out of the record data to be inserted, and save it.
 	 */
-	key.ir_startino = recp->ir_startino; /* INT_: direct copy */
+	key.ir_startino = recp->ir_startino;
 	optr = ptr = cur->bc_ptrs[level];
 	/*
 	 * If we're off the left edge, return failure.
@@ -600,7 +600,7 @@
 	}
 #endif
 	nbno = NULLAGBLOCK;
-	ncur = (xfs_btree_cur_t *)0;
+	ncur = NULL;
 	/*
 	 * If the block is full, we can't insert the new entry until we
 	 * make the block un-full.
@@ -641,7 +641,7 @@
 						return error;
 #endif
 					ptr = cur->bc_ptrs[level];
-					nrec.ir_startino = nkey.ir_startino; /* INT_: direct copy */
+					nrec.ir_startino = nkey.ir_startino;
 				} else {
 					/*
 					 * Otherwise the insert fails.
@@ -681,7 +681,7 @@
 		if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
 			return error;
 #endif
-		kp[ptr - 1] = key; /* INT_: struct copy */
+		kp[ptr - 1] = key;
 		pp[ptr - 1] = cpu_to_be32(*bnop);
 		numrecs++;
 		block->bb_numrecs = cpu_to_be16(numrecs);
@@ -698,7 +698,7 @@
 		 * Now stuff the new record in, bump numrecs
 		 * and log the new data.
 		 */
-		rp[ptr - 1] = *recp; /* INT_: struct copy */
+		rp[ptr - 1] = *recp;
 		numrecs++;
 		block->bb_numrecs = cpu_to_be16(numrecs);
 		xfs_inobt_log_recs(cur, bp, ptr, numrecs);
@@ -731,7 +731,7 @@
 	 */
 	*bnop = nbno;
 	if (nbno != NULLAGBLOCK) {
-		*recp = nrec; /* INT_: struct copy */
+		*recp = nrec;
 		*curp = ncur;
 	}
 	*stat = 1;
@@ -878,7 +878,7 @@
 		 */
 		bp = cur->bc_bufs[level];
 		if (bp && XFS_BUF_ADDR(bp) != d)
-			bp = (xfs_buf_t *)0;
+			bp = NULL;
 		if (!bp) {
 			/*
 			 * Need to get a new buffer.  Read it, then
@@ -950,12 +950,12 @@
 					xfs_inobt_key_t	*kkp;
 
 					kkp = kkbase + keyno - 1;
-					startino = INT_GET(kkp->ir_startino, ARCH_CONVERT);
+					startino = be32_to_cpu(kkp->ir_startino);
 				} else {
 					xfs_inobt_rec_t	*krp;
 
 					krp = krbase + keyno - 1;
-					startino = INT_GET(krp->ir_startino, ARCH_CONVERT);
+					startino = be32_to_cpu(krp->ir_startino);
 				}
 				/*
 				 * Compute difference to get next direction.
@@ -1117,7 +1117,7 @@
 		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level)))
 			return error;
 #endif
-		*lpp = *rpp; /* INT_: no-change copy */
+		*lpp = *rpp;
 		xfs_inobt_log_ptrs(cur, lbp, nrec, nrec);
 	}
 	/*
@@ -1160,7 +1160,7 @@
 	} else {
 		memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
 		xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-		key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
+		key.ir_startino = rrp->ir_startino;
 		rkp = &key;
 	}
 	/*
@@ -1297,13 +1297,13 @@
 	 */
 	kp = XFS_INOBT_KEY_ADDR(new, 1, cur);
 	if (be16_to_cpu(left->bb_level) > 0) {
-		kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur); /* INT_: struct copy */
-		kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur); /* INT_: struct copy */
+		kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur);
+		kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur);
 	} else {
 		rp = XFS_INOBT_REC_ADDR(left, 1, cur);
-		INT_COPY(kp[0].ir_startino, rp->ir_startino, ARCH_CONVERT);
+		kp[0].ir_startino = rp->ir_startino;
 		rp = XFS_INOBT_REC_ADDR(right, 1, cur);
-		INT_COPY(kp[1].ir_startino, rp->ir_startino, ARCH_CONVERT);
+		kp[1].ir_startino = rp->ir_startino;
 	}
 	xfs_inobt_log_keys(cur, nbp, 1, 2);
 	/*
@@ -1410,8 +1410,8 @@
 		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*lpp), level)))
 			return error;
 #endif
-		*rkp = *lkp; /* INT_: no change copy */
-		*rpp = *lpp; /* INT_: no change copy */
+		*rkp = *lkp;
+		*rpp = *lpp;
 		xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
 		xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
 	} else {
@@ -1420,7 +1420,7 @@
 		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
 		*rrp = *lrp;
 		xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
-		key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
+		key.ir_startino = rrp->ir_startino;
 		rkp = &key;
 	}
 	/*
@@ -1559,7 +1559,7 @@
 		rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
 		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
 		xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-		keyp->ir_startino = rrp->ir_startino; /* INT_: direct copy */
+		keyp->ir_startino = rrp->ir_startino;
 	}
 	/*
 	 * Find the left block number by looking in the buffer.
@@ -1813,9 +1813,9 @@
 	 * Point to the record and extract its data.
 	 */
 	rec = XFS_INOBT_REC_ADDR(block, ptr, cur);
-	*ino = INT_GET(rec->ir_startino, ARCH_CONVERT);
-	*fcnt = INT_GET(rec->ir_freecount, ARCH_CONVERT);
-	*free = INT_GET(rec->ir_free, ARCH_CONVERT);
+	*ino = be32_to_cpu(rec->ir_startino);
+	*fcnt = be32_to_cpu(rec->ir_freecount);
+	*free = be64_to_cpu(rec->ir_free);
 	*stat = 1;
 	return 0;
 }
@@ -1930,10 +1930,10 @@
 
 	level = 0;
 	nbno = NULLAGBLOCK;
-	INT_SET(nrec.ir_startino, ARCH_CONVERT, cur->bc_rec.i.ir_startino);
-	INT_SET(nrec.ir_freecount, ARCH_CONVERT, cur->bc_rec.i.ir_freecount);
-	INT_SET(nrec.ir_free, ARCH_CONVERT, cur->bc_rec.i.ir_free);
-	ncur = (xfs_btree_cur_t *)0;
+	nrec.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino);
+	nrec.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount);
+	nrec.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);
+	ncur = NULL;
 	pcur = cur;
 	/*
 	 * Loop going up the tree, starting at the leaf level.
@@ -1965,7 +1965,7 @@
 		 */
 		if (ncur) {
 			pcur = ncur;
-			ncur = (xfs_btree_cur_t *)0;
+			ncur = NULL;
 		}
 	} while (nbno != NULLAGBLOCK);
 	*stat = i;
@@ -2060,9 +2060,9 @@
 	/*
 	 * Fill in the new contents and log them.
 	 */
-	INT_SET(rp->ir_startino, ARCH_CONVERT, ino);
-	INT_SET(rp->ir_freecount, ARCH_CONVERT, fcnt);
-	INT_SET(rp->ir_free, ARCH_CONVERT, free);
+	rp->ir_startino = cpu_to_be32(ino);
+	rp->ir_freecount = cpu_to_be32(fcnt);
+	rp->ir_free = cpu_to_be64(free);
 	xfs_inobt_log_recs(cur, bp, ptr, ptr);
 	/*
 	 * Updating first record in leaf. Pass new key value up to our parent.
@@ -2070,7 +2070,7 @@
 	if (ptr == 1) {
 		xfs_inobt_key_t	key;	/* key containing [ino] */
 
-		INT_SET(key.ir_startino, ARCH_CONVERT, ino);
+		key.ir_startino = cpu_to_be32(ino);
 		if ((error = xfs_inobt_updkey(cur, &key, 1)))
 			return error;
 	}
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index ae3904c..2c0e498 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -47,19 +47,24 @@
 /*
  * Data record structure
  */
-typedef struct xfs_inobt_rec
-{
+typedef struct xfs_inobt_rec {
+	__be32		ir_startino;	/* starting inode number */
+	__be32		ir_freecount;	/* count of free inodes (set bits) */
+	__be64		ir_free;	/* free inode mask */
+} xfs_inobt_rec_t;
+
+typedef struct xfs_inobt_rec_incore {
 	xfs_agino_t	ir_startino;	/* starting inode number */
 	__int32_t	ir_freecount;	/* count of free inodes (set bits) */
 	xfs_inofree_t	ir_free;	/* free inode mask */
-} xfs_inobt_rec_t;
+} xfs_inobt_rec_incore_t;
+
 
 /*
  * Key structure
  */
-typedef struct xfs_inobt_key
-{
-	xfs_agino_t	ir_startino;	/* starting inode number */
+typedef struct xfs_inobt_key {
+	__be32		ir_startino;	/* starting inode number */
 } xfs_inobt_key_t;
 
 /* btree pointer type */
@@ -77,7 +82,7 @@
 #define	XFS_INOBT_IS_FREE(rp,i)		\
 		(((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
 #define	XFS_INOBT_IS_FREE_DISK(rp,i)	\
-		((INT_GET((rp)->ir_free,ARCH_CONVERT) & XFS_INOBT_MASK(i)) != 0)
+		((be64_to_cpu((rp)->ir_free) & XFS_INOBT_MASK(i)) != 0)
 #define	XFS_INOBT_SET_FREE(rp,i)	((rp)->ir_free |= XFS_INOBT_MASK(i))
 #define	XFS_INOBT_CLR_FREE(rp,i)	((rp)->ir_free &= ~XFS_INOBT_MASK(i))
 
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 0724df7..b73d216 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -50,7 +50,7 @@
 xfs_ihash_init(xfs_mount_t *mp)
 {
 	__uint64_t	icount;
-	uint		i, flags = KM_SLEEP | KM_MAYFAIL;
+	uint		i;
 
 	if (!mp->m_ihsize) {
 		icount = mp->m_maxicount ? mp->m_maxicount :
@@ -61,14 +61,13 @@
 					(64 * NBPP) / sizeof(xfs_ihash_t));
 	}
 
-	while (!(mp->m_ihash = (xfs_ihash_t *)kmem_zalloc(mp->m_ihsize *
-						sizeof(xfs_ihash_t), flags))) {
-		if ((mp->m_ihsize >>= 1) <= NBPP)
-			flags = KM_SLEEP;
-	}
-	for (i = 0; i < mp->m_ihsize; i++) {
+	mp->m_ihash = kmem_zalloc_greedy(&mp->m_ihsize,
+					 NBPC * sizeof(xfs_ihash_t),
+					 mp->m_ihsize * sizeof(xfs_ihash_t),
+					 KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+	mp->m_ihsize /= sizeof(xfs_ihash_t);
+	for (i = 0; i < mp->m_ihsize; i++)
 		rwlock_init(&(mp->m_ihash[i].ih_lock));
-	}
 }
 
 /*
@@ -77,7 +76,7 @@
 void
 xfs_ihash_free(xfs_mount_t *mp)
 {
-	kmem_free(mp->m_ihash, mp->m_ihsize*sizeof(xfs_ihash_t));
+	kmem_free(mp->m_ihash, mp->m_ihsize * sizeof(xfs_ihash_t));
 	mp->m_ihash = NULL;
 }
 
@@ -95,7 +94,7 @@
 	mp->m_chsize = min_t(uint, mp->m_chsize, mp->m_ihsize);
 	mp->m_chash = (xfs_chash_t *)kmem_zalloc(mp->m_chsize
 						 * sizeof(xfs_chash_t),
-						 KM_SLEEP);
+						 KM_SLEEP | KM_LARGE);
 	for (i = 0; i < mp->m_chsize; i++) {
 		spinlock_init(&mp->m_chash[i].ch_lock,"xfshash");
 	}
@@ -244,7 +243,9 @@
 
 				XFS_STATS_INC(xs_ig_found);
 
+				spin_lock(&ip->i_flags_lock);
 				ip->i_flags &= ~XFS_IRECLAIMABLE;
+				spin_unlock(&ip->i_flags_lock);
 				version = ih->ih_version;
 				read_unlock(&ih->ih_lock);
 				xfs_ihash_promote(ih, ip, version);
@@ -290,15 +291,17 @@
 
 finish_inode:
 			if (ip->i_d.di_mode == 0) {
-				if (!(flags & IGET_CREATE))
+				if (!(flags & XFS_IGET_CREATE))
 					return ENOENT;
 				xfs_iocore_inode_reinit(ip);
 			}
-	
+
 			if (lock_flags != 0)
 				xfs_ilock(ip, lock_flags);
 
+			spin_lock(&ip->i_flags_lock);
 			ip->i_flags &= ~XFS_ISTALE;
+			spin_unlock(&ip->i_flags_lock);
 
 			vn_trace_exit(vp, "xfs_iget.found",
 						(inst_t *)__return_address);
@@ -320,21 +323,20 @@
 	 * Read the disk inode attributes into a new inode structure and get
 	 * a new vnode for it. This should also initialize i_ino and i_mount.
 	 */
-	error = xfs_iread(mp, tp, ino, &ip, bno);
-	if (error) {
+	error = xfs_iread(mp, tp, ino, &ip, bno,
+			  (flags & XFS_IGET_BULKSTAT) ? XFS_IMAP_BULKSTAT : 0);
+	if (error)
 		return error;
-	}
 
 	vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address);
 
 	xfs_inode_lock_init(ip, vp);
 	xfs_iocore_inode_init(ip);
 
-	if (lock_flags != 0) {
+	if (lock_flags)
 		xfs_ilock(ip, lock_flags);
-	}
-		
-	if ((ip->i_d.di_mode == 0) && !(flags & IGET_CREATE)) {
+
+	if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
 		xfs_idestroy(ip);
 		return ENOENT;
 	}
@@ -369,7 +371,9 @@
 	ih->ih_next = ip;
 	ip->i_udquot = ip->i_gdquot = NULL;
 	ih->ih_version++;
+	spin_lock(&ip->i_flags_lock);
 	ip->i_flags |= XFS_INEW;
+	spin_unlock(&ip->i_flags_lock);
 
 	write_unlock(&ih->ih_lock);
 
@@ -548,7 +552,7 @@
 	mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", vp->v_number);
 	init_waitqueue_head(&ip->i_ipin_wait);
 	atomic_set(&ip->i_pincount, 0);
-	init_sema(&ip->i_flock, 1, "xfsfino", vp->v_number);
+	initnsema(&ip->i_flock, 1, "xfsfino");
 }
 
 /*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 1f8ecff..c27d7d49 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -854,7 +854,8 @@
 	xfs_trans_t	*tp,
 	xfs_ino_t	ino,
 	xfs_inode_t	**ipp,
-	xfs_daddr_t	bno)
+	xfs_daddr_t	bno,
+	uint		imap_flags)
 {
 	xfs_buf_t	*bp;
 	xfs_dinode_t	*dip;
@@ -866,6 +867,7 @@
 	ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
 	ip->i_ino = ino;
 	ip->i_mount = mp;
+	spin_lock_init(&ip->i_flags_lock);
 
 	/*
 	 * Get pointer's to the on-disk inode and the buffer containing it.
@@ -874,7 +876,7 @@
 	 * return NULL as well.  Set i_blkno to 0 so that xfs_itobp() will
 	 * know that this is a new incore inode.
 	 */
-	error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0);
+	error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags);
 	if (error) {
 		kmem_zone_free(xfs_inode_zone, ip);
 		return error;
@@ -1113,7 +1115,7 @@
 	 * to prevent others from looking at until we're done.
 	 */
 	error = xfs_trans_iget(tp->t_mountp, tp, ino,
-			IGET_CREATE, XFS_ILOCK_EXCL, &ip);
+				XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip);
 	if (error != 0) {
 		return error;
 	}
@@ -2213,7 +2215,9 @@
 
 			if (ip == free_ip) {
 				if (xfs_iflock_nowait(ip)) {
+					spin_lock(&ip->i_flags_lock);
 					ip->i_flags |= XFS_ISTALE;
+					spin_unlock(&ip->i_flags_lock);
 
 					if (xfs_inode_clean(ip)) {
 						xfs_ifunlock(ip);
@@ -2227,7 +2231,9 @@
 
 			if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
 				if (xfs_iflock_nowait(ip)) {
+					spin_lock(&ip->i_flags_lock);
 					ip->i_flags |= XFS_ISTALE;
+					spin_unlock(&ip->i_flags_lock);
 
 					if (xfs_inode_clean(ip)) {
 						xfs_ifunlock(ip);
@@ -2257,7 +2263,9 @@
 				AIL_LOCK(mp,s);
 				iip->ili_flush_lsn = iip->ili_item.li_lsn;
 				AIL_UNLOCK(mp, s);
+				spin_lock(&iip->ili_inode->i_flags_lock);
 				iip->ili_inode->i_flags |= XFS_ISTALE;
+				spin_unlock(&iip->ili_inode->i_flags_lock);
 				pre_flushed++;
 			}
 			lip = lip->li_bio_list;
@@ -2753,19 +2761,29 @@
 		 * call as the inode reclaim may be blocked waiting for
 		 * the inode to become unpinned.
 		 */
+		struct inode *inode = NULL;
+
+		spin_lock(&ip->i_flags_lock);
 		if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
 			bhv_vnode_t	*vp = XFS_ITOV_NULL(ip);
 
 			/* make sync come back and flush this inode */
 			if (vp) {
-				struct inode	*inode = vn_to_inode(vp);
+				inode = vn_to_inode(vp);
 
 				if (!(inode->i_state &
-						(I_NEW|I_FREEING|I_CLEAR)))
-					mark_inode_dirty_sync(inode);
+						(I_NEW|I_FREEING|I_CLEAR))) {
+					inode = igrab(inode);
+					if (inode)
+						mark_inode_dirty_sync(inode);
+				} else
+					inode = NULL;
 			}
 		}
+		spin_unlock(&ip->i_flags_lock);
 		wake_up(&ip->i_ipin_wait);
+		if (inode)
+			iput(inode);
 	}
 }
 
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index d10b76e..e96eb08 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -267,6 +267,7 @@
 	sema_t			i_flock;	/* inode flush lock */
 	atomic_t		i_pincount;	/* inode pin count */
 	wait_queue_head_t	i_ipin_wait;	/* inode pinning wait queue */
+	spinlock_t		i_flags_lock;	/* inode i_flags lock */
 #ifdef HAVE_REFCACHE
 	struct xfs_inode	**i_refcache;	/* ptr to entry in ref cache */
 	struct xfs_inode	*i_release;	/* inode to unref */
@@ -389,11 +390,14 @@
 	(((vfsp)->vfs_flag & VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID))
 
 /*
+ * Flags for xfs_iget()
+ */
+#define XFS_IGET_CREATE		0x1
+#define XFS_IGET_BULKSTAT	0x2
+
+/*
  * xfs_iget.c prototypes.
  */
-
-#define IGET_CREATE	1
-
 void		xfs_ihash_init(struct xfs_mount *);
 void		xfs_ihash_free(struct xfs_mount *);
 void		xfs_chash_init(struct xfs_mount *);
@@ -425,7 +429,7 @@
 			  xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
 			  xfs_daddr_t, uint);
 int		xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-			  xfs_inode_t **, xfs_daddr_t);
+			  xfs_inode_t **, xfs_daddr_t, uint);
 int		xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
 int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
 			   xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index f8e80d8..a7a9225 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -743,21 +743,6 @@
 }
 
 /*
- * The transaction with the inode locked has aborted.  The inode
- * must not be dirty within the transaction (unless we're forcibly
- * shutting down).  We simply unlock just as if the transaction
- * had been cancelled.
- */
-STATIC void
-xfs_inode_item_abort(
-	xfs_inode_log_item_t	*iip)
-{
-	xfs_inode_item_unlock(iip);
-	return;
-}
-
-
-/*
  * This gets called by xfs_trans_push_ail(), when IOP_TRYLOCK
  * failed to get the inode flush lock but did get the inode locked SHARED.
  * Here we're trying to see if the inode buffer is incore, and if so whether it's
@@ -915,7 +900,6 @@
 	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_inode_item_committed,
 	.iop_push	= (void(*)(xfs_log_item_t*))xfs_inode_item_push,
-	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_inode_item_abort,
 	.iop_pushbuf	= (void(*)(xfs_log_item_t*))xfs_inode_item_pushbuf,
 	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
 					xfs_inode_item_committing
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index 5db6cd1..bfe92ea 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -25,52 +25,54 @@
  * must be added on to the end.
  */
 typedef struct xfs_inode_log_format {
-	unsigned short		ilf_type;	/* inode log item type */
-	unsigned short		ilf_size;	/* size of this item */
-	uint			ilf_fields;	/* flags for fields logged */
-	ushort			ilf_asize;	/* size of attr d/ext/root */
-	ushort			ilf_dsize;	/* size of data/ext/root */
-	xfs_ino_t		ilf_ino;	/* inode number */
+	__uint16_t		ilf_type;	/* inode log item type */
+	__uint16_t		ilf_size;	/* size of this item */
+	__uint32_t		ilf_fields;	/* flags for fields logged */
+	__uint16_t		ilf_asize;	/* size of attr d/ext/root */
+	__uint16_t		ilf_dsize;	/* size of data/ext/root */
+	__uint64_t		ilf_ino;	/* inode number */
 	union {
-		xfs_dev_t	ilfu_rdev;	/* rdev value for dev inode*/
+		__uint32_t	ilfu_rdev;	/* rdev value for dev inode*/
 		uuid_t		ilfu_uuid;	/* mount point value */
 	} ilf_u;
 	__int64_t		ilf_blkno;	/* blkno of inode buffer */
-	int			ilf_len;	/* len of inode buffer */
-	int			ilf_boffset;	/* off of inode in buffer */
+	__int32_t		ilf_len;	/* len of inode buffer */
+	__int32_t		ilf_boffset;	/* off of inode in buffer */
 } xfs_inode_log_format_t;
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_inode_log_format_32 {
-	unsigned short		ilf_type;	/* 16: inode log item type */
-	unsigned short		ilf_size;	/* 16: size of this item */
-	uint			ilf_fields;	/* 32: flags for fields logged */
-	ushort			ilf_asize;	/* 32: size of attr d/ext/root */
-	ushort			ilf_dsize;	/* 32: size of data/ext/root */
-	xfs_ino_t		ilf_ino;	/* 64: inode number */
+	__uint16_t		ilf_type;	/* inode log item type */
+	__uint16_t		ilf_size;	/* size of this item */
+	__uint32_t		ilf_fields;	/* flags for fields logged */
+	__uint16_t		ilf_asize;	/* size of attr d/ext/root */
+	__uint16_t		ilf_dsize;	/* size of data/ext/root */
+	__uint64_t		ilf_ino;	/* inode number */
 	union {
-		xfs_dev_t	ilfu_rdev;	/* 32: rdev value for dev inode*/
-		uuid_t		ilfu_uuid;	/* 128: mount point value */
+		__uint32_t	ilfu_rdev;	/* rdev value for dev inode*/
+		uuid_t		ilfu_uuid;	/* mount point value */
 	} ilf_u;
-	__int64_t		ilf_blkno;	/* 64: blkno of inode buffer */
-	int			ilf_len;	/* 32: len of inode buffer */
-	int			ilf_boffset;	/* 32: off of inode in buffer */
+	__int64_t		ilf_blkno;	/* blkno of inode buffer */
+	__int32_t		ilf_len;	/* len of inode buffer */
+	__int32_t		ilf_boffset;	/* off of inode in buffer */
 } __attribute__((packed)) xfs_inode_log_format_32_t;
+#endif
 
 typedef struct xfs_inode_log_format_64 {
-	unsigned short		ilf_type;	/* 16: inode log item type */
-	unsigned short		ilf_size;	/* 16: size of this item */
-	uint			ilf_fields;	/* 32: flags for fields logged */
-	ushort			ilf_asize;	/* 32: size of attr d/ext/root */
-	ushort			ilf_dsize;	/* 32: size of data/ext/root */
-	__uint32_t		ilf_pad;	/* 32: pad for 64 bit boundary */
-	xfs_ino_t		ilf_ino;	/* 64: inode number */
+	__uint16_t		ilf_type;	/* inode log item type */
+	__uint16_t		ilf_size;	/* size of this item */
+	__uint32_t		ilf_fields;	/* flags for fields logged */
+	__uint16_t		ilf_asize;	/* size of attr d/ext/root */
+	__uint16_t		ilf_dsize;	/* size of data/ext/root */
+	__uint32_t		ilf_pad;	/* pad for 64 bit boundary */
+	__uint64_t		ilf_ino;	/* inode number */
 	union {
-		xfs_dev_t	ilfu_rdev;	/* 32: rdev value for dev inode*/
-		uuid_t		ilfu_uuid;	/* 128: mount point value */
+		__uint32_t	ilfu_rdev;	/* rdev value for dev inode*/
+		uuid_t		ilfu_uuid;	/* mount point value */
 	} ilf_u;
-	__int64_t		ilf_blkno;	/* 64: blkno of inode buffer */
-	int			ilf_len;	/* 32: len of inode buffer */
-	int			ilf_boffset;	/* 32: off of inode in buffer */
+	__int64_t		ilf_blkno;	/* blkno of inode buffer */
+	__int32_t		ilf_len;	/* len of inode buffer */
+	__int32_t		ilf_boffset;	/* off of inode in buffer */
 } xfs_inode_log_format_64_t;
 
 /*
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index f1949c1..1965512 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -398,6 +398,23 @@
 	return 1;
 }
 
+STATIC int
+xfs_cmn_err_fsblock_zero(
+	xfs_inode_t	*ip,
+	xfs_bmbt_irec_t	*imap)
+{
+	xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+			"Access to block zero in inode %llu "
+			"start_block: %llx start_off: %llx "
+			"blkcnt: %llx extent-state: %x\n",
+		(unsigned long long)ip->i_ino,
+		(unsigned long long)imap->br_startblock,
+		(unsigned long long)imap->br_startoff,
+		(unsigned long long)imap->br_blockcount,
+		imap->br_state);
+	return EFSCORRUPTED;
+}
+
 int
 xfs_iomap_write_direct(
 	xfs_inode_t	*ip,
@@ -536,23 +553,17 @@
 	 * Copy any maps to caller's array and return any error.
 	 */
 	if (nimaps == 0) {
-		error = (ENOSPC);
+		error = ENOSPC;
+		goto error_out;
+	}
+
+	if (unlikely(!imap.br_startblock && !(io->io_flags & XFS_IOCORE_RT))) {
+		error = xfs_cmn_err_fsblock_zero(ip, &imap);
 		goto error_out;
 	}
 
 	*ret_imap = imap;
 	*nmaps = 1;
-	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
-                cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
-                        "start_block : %llx start_off : %llx blkcnt : %llx "
-                        "extent-state : %x \n",
-                        (ip->i_mount)->m_fsname,
-                        (long long)ip->i_ino,
-                        (unsigned long long)ret_imap->br_startblock,
-			(unsigned long long)ret_imap->br_startoff,
-                        (unsigned long long)ret_imap->br_blockcount,
-			ret_imap->br_state);
-        }
 	return 0;
 
 error0:	/* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
@@ -715,17 +726,8 @@
 		goto retry;
 	}
 
-	if (!(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
-		cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
-                        "start_block : %llx start_off : %llx blkcnt : %llx "
-                        "extent-state : %x \n",
-                        (ip->i_mount)->m_fsname,
-                        (long long)ip->i_ino,
-                        (unsigned long long)ret_imap->br_startblock,
-			(unsigned long long)ret_imap->br_startoff,
-                        (unsigned long long)ret_imap->br_blockcount,
-			ret_imap->br_state);
-	}
+	if (unlikely(!imap[0].br_startblock && !(io->io_flags & XFS_IOCORE_RT)))
+		return xfs_cmn_err_fsblock_zero(ip, &imap[0]);
 
 	*ret_imap = imap[0];
 	*nmaps = 1;
@@ -853,24 +855,10 @@
 		 * See if we were able to allocate an extent that
 		 * covers at least part of the callers request
 		 */
-
 		for (i = 0; i < nimaps; i++) {
-			if (!(io->io_flags & XFS_IOCORE_RT)  &&
-			    !imap[i].br_startblock) {
-				cmn_err(CE_PANIC,"Access to block zero:  "
-					"fs <%s> inode: %lld "
-					"start_block : %llx start_off : %llx "
-					"blkcnt : %llx extent-state : %x \n",
-					(ip->i_mount)->m_fsname,
-					(long long)ip->i_ino,
-					(unsigned long long)
-						imap[i].br_startblock,
-					(unsigned long long)
-						imap[i].br_startoff,
-					(unsigned long long)
-				        	imap[i].br_blockcount,
-					imap[i].br_state);
-                        }
+			if (unlikely(!imap[i].br_startblock &&
+				     !(io->io_flags & XFS_IOCORE_RT)))
+				return xfs_cmn_err_fsblock_zero(ip, &imap[i]);
 			if ((offset_fsb >= imap[i].br_startoff) &&
 			    (offset_fsb < (imap[i].br_startoff +
 					   imap[i].br_blockcount))) {
@@ -941,7 +929,7 @@
 				XFS_WRITE_LOG_COUNT);
 		if (error) {
 			xfs_trans_cancel(tp, 0);
-			goto error0;
+			return XFS_ERROR(error);
 		}
 
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -967,19 +955,11 @@
 		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
-			goto error0;
+			return XFS_ERROR(error);
 
-		if ( !(io->io_flags & XFS_IOCORE_RT)  && !imap.br_startblock) {
-			cmn_err(CE_PANIC,"Access to block zero:  fs <%s> "
-				"inode: %lld start_block : %llx start_off : "
-				"%llx blkcnt : %llx extent-state : %x \n",
-				(ip->i_mount)->m_fsname,
-				(long long)ip->i_ino,
-				(unsigned long long)imap.br_startblock,
-				(unsigned long long)imap.br_startoff,
-				(unsigned long long)imap.br_blockcount,
-				imap.br_state);
-        	}
+		if (unlikely(!imap.br_startblock &&
+			     !(io->io_flags & XFS_IOCORE_RT)))
+			return xfs_cmn_err_fsblock_zero(ip, &imap);
 
 		if ((numblks_fsb = imap.br_blockcount) == 0) {
 			/*
@@ -999,6 +979,5 @@
 	xfs_bmap_cancel(&free_list);
 	xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT));
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-error0:
 	return XFS_ERROR(error);
 }
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 46249e4..7775ddc 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -39,6 +39,16 @@
 #include "xfs_error.h"
 #include "xfs_btree.h"
 
+int
+xfs_internal_inum(
+	xfs_mount_t	*mp,
+	xfs_ino_t	ino)
+{
+	return (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
+		(XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
+		 (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)));
+}
+
 STATIC int
 xfs_bulkstat_one_iget(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
@@ -52,7 +62,8 @@
 	bhv_vnode_t	*vp;
 	int		error;
 
-	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
+	error = xfs_iget(mp, NULL, ino,
+			 XFS_IGET_BULKSTAT, XFS_ILOCK_SHARED, &ip, bno);
 	if (error) {
 		*stat = BULKSTAT_RV_NOTHING;
 		return error;
@@ -212,17 +223,12 @@
 	xfs_dinode_t	*dip;		/* dinode inode pointer */
 
 	dip = (xfs_dinode_t *)dibuff;
+	*stat = BULKSTAT_RV_NOTHING;
 
-	if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
-	    (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
-	     (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) {
-		*stat = BULKSTAT_RV_NOTHING;
+	if (!buffer || xfs_internal_inum(mp, ino))
 		return XFS_ERROR(EINVAL);
-	}
-	if (ubsize < sizeof(*buf)) {
-		*stat = BULKSTAT_RV_NOTHING;
+	if (ubsize < sizeof(*buf))
 		return XFS_ERROR(ENOMEM);
-	}
 
 	buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
 
@@ -238,8 +244,7 @@
 	}
 
 	if (copy_to_user(buffer, buf, sizeof(*buf)))  {
-		*stat = BULKSTAT_RV_NOTHING;
-		error =  EFAULT;
+		error = EFAULT;
 		goto out_free;
 	}
 
@@ -253,6 +258,46 @@
 }
 
 /*
+ * Test to see whether we can use the ondisk inode directly, based
+ * on the given bulkstat flags, filling in dipp accordingly.
+ * Returns zero if the inode is dodgey.
+ */
+STATIC int
+xfs_bulkstat_use_dinode(
+	xfs_mount_t	*mp,
+	int		flags,
+	xfs_buf_t	*bp,
+	int		clustidx,
+	xfs_dinode_t	**dipp)
+{
+	xfs_dinode_t	*dip;
+	unsigned int	aformat;
+
+	*dipp = NULL;
+	if (!bp || (flags & BULKSTAT_FG_IGET))
+		return 1;
+	dip = (xfs_dinode_t *)
+			xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
+	if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC ||
+	    !XFS_DINODE_GOOD_VERSION(
+			INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
+		return 0;
+	if (flags & BULKSTAT_FG_QUICK) {
+		*dipp = dip;
+		return 1;
+	}
+	/* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
+	aformat = INT_GET(dip->di_core.di_aformat, ARCH_CONVERT);
+	if ((XFS_CFORK_Q(&dip->di_core) == 0) ||
+	    (aformat == XFS_DINODE_FMT_LOCAL) ||
+	    (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) {
+		*dipp = dip;
+		return 1;
+	}
+	return 1;
+}
+
+/*
  * Return stat information in bulk (by-inode) for the filesystem.
  */
 int					/* error status */
@@ -284,10 +329,11 @@
 	xfs_agino_t		gino;	/* current btree rec's start inode */
 	int			i;	/* loop index */
 	int			icount;	/* count of inodes good in irbuf */
+	size_t			irbsize; /* size of irec buffer in bytes */
 	xfs_ino_t		ino;	/* inode number (filesystem) */
-	xfs_inobt_rec_t		*irbp;	/* current irec buffer pointer */
-	xfs_inobt_rec_t		*irbuf;	/* start of irec buffer */
-	xfs_inobt_rec_t		*irbufend; /* end of good irec buffer entries */
+	xfs_inobt_rec_incore_t	*irbp;	/* current irec buffer pointer */
+	xfs_inobt_rec_incore_t	*irbuf;	/* start of irec buffer */
+	xfs_inobt_rec_incore_t	*irbufend; /* end of good irec buffer entries */
 	xfs_ino_t		lastino=0; /* last inode number returned */
 	int			nbcluster; /* # of blocks in a cluster */
 	int			nicluster; /* # of inodes in a cluster */
@@ -328,13 +374,10 @@
 		(XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
 	nimask = ~(nicluster - 1);
 	nbcluster = nicluster >> mp->m_sb.sb_inopblog;
-	/*
-	 * Allocate a page-sized buffer for inode btree records.
-	 * We could try allocating something smaller, but for normal
-	 * calls we'll always (potentially) need the whole page.
-	 */
-	irbuf = kmem_alloc(NBPC, KM_SLEEP);
-	nirbuf = NBPC / sizeof(*irbuf);
+	irbuf = kmem_zalloc_greedy(&irbsize, NBPC, NBPC * 4,
+				   KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+	nirbuf = irbsize / sizeof(*irbuf);
+
 	/*
 	 * Loop over the allocation groups, starting from the last
 	 * inode returned; 0 means start of the allocation group.
@@ -358,7 +401,7 @@
 		 * Allocate and initialize a btree cursor for ialloc btree.
 		 */
 		cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO,
-			(xfs_inode_t *)0, 0);
+						(xfs_inode_t *)0, 0);
 		irbp = irbuf;
 		irbufend = irbuf + nirbuf;
 		end_of_ag = 0;
@@ -395,9 +438,9 @@
 						gcnt++;
 				}
 				gfree |= XFS_INOBT_MASKN(0, chunkidx);
-				INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
-				INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
-				INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
+				irbp->ir_startino = gino;
+				irbp->ir_freecount = gcnt;
+				irbp->ir_free = gfree;
 				irbp++;
 				agino = gino + XFS_INODES_PER_CHUNK;
 				icount = XFS_INODES_PER_CHUNK - gcnt;
@@ -451,11 +494,27 @@
 			}
 			/*
 			 * If this chunk has any allocated inodes, save it.
+			 * Also start read-ahead now for this chunk.
 			 */
 			if (gcnt < XFS_INODES_PER_CHUNK) {
-				INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
-				INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
-				INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
+				/*
+				 * Loop over all clusters in the next chunk.
+				 * Do a readahead if there are any allocated
+				 * inodes in that cluster.
+				 */
+				for (agbno = XFS_AGINO_TO_AGBNO(mp, gino),
+				     chunkidx = 0;
+				     chunkidx < XFS_INODES_PER_CHUNK;
+				     chunkidx += nicluster,
+				     agbno += nbcluster) {
+					if (XFS_INOBT_MASKN(chunkidx,
+							    nicluster) & ~gfree)
+						xfs_btree_reada_bufs(mp, agno,
+							agbno, nbcluster);
+				}
+				irbp->ir_startino = gino;
+				irbp->ir_freecount = gcnt;
+				irbp->ir_free = gfree;
 				irbp++;
 				icount += XFS_INODES_PER_CHUNK - gcnt;
 			}
@@ -479,33 +538,11 @@
 		for (irbp = irbuf;
 		     irbp < irbufend && ubleft >= statstruct_size; irbp++) {
 			/*
-			 * Read-ahead the next chunk's worth of inodes.
-			 */
-			if (&irbp[1] < irbufend) {
-				/*
-				 * Loop over all clusters in the next chunk.
-				 * Do a readahead if there are any allocated
-				 * inodes in that cluster.
-				 */
-				for (agbno = XFS_AGINO_TO_AGBNO(mp,
-							INT_GET(irbp[1].ir_startino, ARCH_CONVERT)),
-				     chunkidx = 0;
-				     chunkidx < XFS_INODES_PER_CHUNK;
-				     chunkidx += nicluster,
-				     agbno += nbcluster) {
-					if (XFS_INOBT_MASKN(chunkidx,
-							    nicluster) &
-					    ~(INT_GET(irbp[1].ir_free, ARCH_CONVERT)))
-						xfs_btree_reada_bufs(mp, agno,
-							agbno, nbcluster);
-				}
-			}
-			/*
 			 * Now process this chunk of inodes.
 			 */
-			for (agino = INT_GET(irbp->ir_startino, ARCH_CONVERT), chunkidx = 0, clustidx = 0;
+			for (agino = irbp->ir_startino, chunkidx = clustidx = 0;
 			     ubleft > 0 &&
-				INT_GET(irbp->ir_freecount, ARCH_CONVERT) < XFS_INODES_PER_CHUNK;
+				irbp->ir_freecount < XFS_INODES_PER_CHUNK;
 			     chunkidx++, clustidx++, agino++) {
 				ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
 				/*
@@ -525,11 +562,12 @@
 				 */
 				if ((chunkidx & (nicluster - 1)) == 0) {
 					agbno = XFS_AGINO_TO_AGBNO(mp,
-							INT_GET(irbp->ir_startino, ARCH_CONVERT)) +
+							irbp->ir_startino) +
 						((chunkidx & nimask) >>
 						 mp->m_sb.sb_inopblog);
 
-					if (flags & BULKSTAT_FG_QUICK) {
+					if (flags & (BULKSTAT_FG_QUICK |
+						     BULKSTAT_FG_INLINE)) {
 						ino = XFS_AGINO_TO_INO(mp, agno,
 								       agino);
 						bno = XFS_AGB_TO_DADDR(mp, agno,
@@ -543,6 +581,7 @@
 								      KM_SLEEP);
 						ip->i_ino = ino;
 						ip->i_mount = mp;
+						spin_lock_init(&ip->i_flags_lock);
 						if (bp)
 							xfs_buf_relse(bp);
 						error = xfs_itobp(mp, NULL, ip,
@@ -564,30 +603,34 @@
 				/*
 				 * Skip if this inode is free.
 				 */
-				if (XFS_INOBT_MASK(chunkidx) & INT_GET(irbp->ir_free, ARCH_CONVERT))
+				if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free)
 					continue;
 				/*
 				 * Count used inodes as free so we can tell
 				 * when the chunk is used up.
 				 */
-				INT_MOD(irbp->ir_freecount, ARCH_CONVERT, +1);
+				irbp->ir_freecount++;
 				ino = XFS_AGINO_TO_INO(mp, agno, agino);
 				bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
-				if (flags & BULKSTAT_FG_QUICK) {
-					dip = (xfs_dinode_t *)xfs_buf_offset(bp,
-					      (clustidx << mp->m_sb.sb_inodelog));
-
-					if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT)
-						    != XFS_DINODE_MAGIC
-					    || !XFS_DINODE_GOOD_VERSION(
-						    INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
-						continue;
+				if (!xfs_bulkstat_use_dinode(mp, flags, bp,
+							     clustidx, &dip))
+					continue;
+				/*
+				 * If we need to do an iget, cannot hold bp.
+				 * Drop it, until starting the next cluster.
+				 */
+				if ((flags & BULKSTAT_FG_INLINE) && !dip) {
+					if (bp)
+						xfs_buf_relse(bp);
+					bp = NULL;
 				}
 
 				/*
 				 * Get the inode and fill in a single buffer.
 				 * BULKSTAT_FG_QUICK uses dip to fill it in.
 				 * BULKSTAT_FG_IGET uses igets.
+				 * BULKSTAT_FG_INLINE uses dip if we have an
+				 * inline attr fork, else igets.
 				 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
 				 * This is also used to count inodes/blks, etc
 				 * in xfs_qm_quotacheck.
@@ -597,8 +640,15 @@
 						ubleft, private_data,
 						bno, &ubused, dip, &fmterror);
 				if (fmterror == BULKSTAT_RV_NOTHING) {
-					if (error == ENOMEM)
+                                        if (error == EFAULT) {
+                                                ubleft = 0;
+                                                rval = error;
+                                                break;
+                                        }
+					else if (error == ENOMEM)
 						ubleft = 0;
+					else
+						lastino = ino;
 					continue;
 				}
 				if (fmterror == BULKSTAT_RV_GIVEUP) {
@@ -633,7 +683,7 @@
 	/*
 	 * Done, we're either out of filesystem or space to put the data.
 	 */
-	kmem_free(irbuf, NBPC);
+	kmem_free(irbuf, irbsize);
 	*ubcountp = ubelem;
 	if (agno >= mp->m_sb.sb_agcount) {
 		/*
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index be5f12e..f25a288 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -36,15 +36,16 @@
 /*
  * Values for stat return value.
  */
-#define	BULKSTAT_RV_NOTHING	0
-#define	BULKSTAT_RV_DIDONE	1
-#define	BULKSTAT_RV_GIVEUP	2
+#define BULKSTAT_RV_NOTHING	0
+#define BULKSTAT_RV_DIDONE	1
+#define BULKSTAT_RV_GIVEUP	2
 
 /*
  * Values for bulkstat flag argument.
  */
-#define	BULKSTAT_FG_IGET	0x1	/* Go through the buffer cache */
-#define	BULKSTAT_FG_QUICK	0x2	/* No iget, walk the dinode cluster */
+#define BULKSTAT_FG_IGET	0x1	/* Go through the buffer cache */
+#define BULKSTAT_FG_QUICK	0x2	/* No iget, walk the dinode cluster */
+#define BULKSTAT_FG_INLINE	0x4	/* No iget if inline attrs */
 
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
@@ -80,6 +81,11 @@
 	void			*dibuff,
 	int			*stat);
 
+int
+xfs_internal_inum(
+	xfs_mount_t		*mp,
+	xfs_ino_t		ino);
+
 int					/* error status */
 xfs_inumbers(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 21ac1a6..c48bf61 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -617,7 +617,8 @@
 		reg[0].i_len  = sizeof(magic);
 		XLOG_VEC_SET_TYPE(&reg[0], XLOG_REG_TYPE_UNMOUNT);
 
-		error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0, 0);
+		error = xfs_log_reserve(mp, 600, 1, &tic,
+					XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE);
 		if (!error) {
 			/* remove inited flag */
 			((xlog_ticket_t *)tic)->t_flags = 0;
@@ -655,8 +656,11 @@
 		} else {
 			LOG_UNLOCK(log, s);
 		}
-		if (tic)
+		if (tic) {
+			xlog_trace_loggrant(log, tic, "unmount rec");
+			xlog_ungrant_log_space(log, tic);
 			xlog_state_put_ticket(log, tic);
+		}
 	} else {
 		/*
 		 * We're already in forced_shutdown mode, couldn't
@@ -1196,7 +1200,7 @@
 			  kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
 		iclog = *iclogp;
 		iclog->hic_data = (xlog_in_core_2_t *)
-			  kmem_zalloc(iclogsize, KM_SLEEP);
+			  kmem_zalloc(iclogsize, KM_SLEEP | KM_LARGE);
 
 		iclog->ic_prev = prev_iclog;
 		prev_iclog = iclog;
@@ -2212,9 +2216,13 @@
 
 			iclog = iclog->ic_next;
 		} while (first_iclog != iclog);
-		if (repeats && (repeats % 10) == 0) {
+
+		if (repeats > 5000) {
+			flushcnt += repeats;
+			repeats = 0;
 			xfs_fs_cmn_err(CE_WARN, log->l_mp,
-				"xlog_state_do_callback: looping %d", repeats);
+				"%s: possible infinite loop (%d iterations)",
+				__FUNCTION__, flushcnt);
 		}
 	} while (!ioerrors && loopdidcallbacks);
 
@@ -2246,6 +2254,7 @@
 	}
 #endif
 
+	flushcnt = 0;
 	if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) {
 		flushcnt = log->l_flushcnt;
 		log->l_flushcnt = 0;
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index eacb3d4..ebbe93f 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -48,16 +48,10 @@
  */
 
 /*
- * Flags to xfs_log_mount
- */
-#define XFS_LOG_RECOVER		0x1
-
-/*
  * Flags to xfs_log_done()
  */
 #define XFS_LOG_REL_PERM_RESERV	0x1
 
-
 /*
  * Flags to xfs_log_reserve()
  *
@@ -70,8 +64,6 @@
 #define XFS_LOG_SLEEP		0x0
 #define XFS_LOG_NOSLEEP		0x1
 #define XFS_LOG_PERM_RESERV	0x2
-#define XFS_LOG_RESV_ALL	(XFS_LOG_NOSLEEP|XFS_LOG_PERM_RESERV)
-
 
 /*
  * Flags to xfs_log_force()
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 34bcbf5..9bd3cdf 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -32,7 +32,6 @@
 #define XLOG_MIN_ICLOGS		2
 #define XLOG_MED_ICLOGS		4
 #define XLOG_MAX_ICLOGS		8
-#define XLOG_CALLBACK_SIZE	10
 #define XLOG_HEADER_MAGIC_NUM	0xFEEDbabe	/* Invalid cycle number */
 #define XLOG_VERSION_1		1
 #define XLOG_VERSION_2		2		/* Large IClogs, Log sunit */
@@ -149,9 +148,6 @@
 #define XLOG_WAS_CONT_TRANS	0x08	/* Cont this trans into new region */
 #define XLOG_END_TRANS		0x10	/* End a continued transaction */
 #define XLOG_UNMOUNT_TRANS	0x20	/* Unmount a filesystem transaction */
-#define XLOG_SKIP_TRANS		(XLOG_COMMIT_TRANS | XLOG_CONTINUE_TRANS | \
-				 XLOG_WAS_CONT_TRANS | XLOG_END_TRANS | \
-				 XLOG_UNMOUNT_TRANS)
 
 #ifdef __KERNEL__
 /*
@@ -506,6 +502,12 @@
 #define XLOG_TRACE_SLEEP_FLUSH 3
 #define XLOG_TRACE_WAKE_FLUSH  4
 
+/*
+ * Unmount record type is used as a pseudo transaction type for the ticket.
+ * It's value must be outside the range of XFS_TRANS_* values.
+ */
+#define XLOG_UNMOUNT_REC_TYPE	(-1U)
+
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_LOG_PRIV_H__ */
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index b2bd4be..e5f396f 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -331,7 +331,7 @@
 	xfs_agnumber_t		m_agirotor;	/* last ag dir inode alloced */
 	lock_t			m_agirotor_lock;/* .. and lock protecting it */
 	xfs_agnumber_t		m_maxagi;	/* highest inode alloc group */
-	uint			m_ihsize;	/* size of next field */
+	size_t			m_ihsize;	/* size of next field */
 	struct xfs_ihash	*m_ihash;	/* fs private inode hash table*/
 	struct xfs_inode	*m_inodes;	/* active inode list */
 	struct list_head	m_del_inodes;	/* inodes to reclaim */
@@ -541,7 +541,8 @@
 #define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
 static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs)
 {
-	return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops));
+	return XFS_BHVTOM(bhv_lookup_range(VFS_BHVHEAD(vfs),
+				VFS_POSITION_XFS, VFS_POSITION_XFS));
 }
 
 #define XFS_DADDR_TO_AGNO(mp,d)         xfs_daddr_to_agno(mp,d)
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index acb853b..9dcb32a 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -281,8 +281,6 @@
 				 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
 				 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
 				 XFS_GQUOTA_ACCT)
-#define XFS_MOUNT_QUOTA_MASK	(XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
-				 XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
 
 
 /*
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 5a0b678..880c732 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1948,7 +1948,7 @@
 	 */
 	nrextents = nrblocks;
 	do_div(nrextents, in->extsize);
-	nrbmblocks = roundup_64(nrextents, NBBY * sbp->sb_blocksize);
+	nrbmblocks = howmany_64(nrextents, NBBY * sbp->sb_blocksize);
 	nrextslog = xfs_highbit32(nrextents);
 	nrsumlevels = nrextslog + 1;
 	nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
@@ -1976,7 +1976,10 @@
 	if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks,
 			mp->m_sb.sb_rsumino)))
 		return error;
-	nmp = NULL;
+	/*
+	 * Allocate a new (fake) mount/sb.
+	 */
+	nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
 	/*
 	 * Loop over the bitmap blocks.
 	 * We will do everything one bitmap block at a time.
@@ -1987,10 +1990,6 @@
 		     ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
 	     bmbno < nrbmblocks;
 	     bmbno++) {
-		/*
-		 * Allocate a new (fake) mount/sb.
-		 */
-		nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
 		*nmp = *mp;
 		nsbp = &nmp->m_sb;
 		/*
@@ -2018,13 +2017,13 @@
 		cancelflags = 0;
 		if ((error = xfs_trans_reserve(tp, 0,
 				XFS_GROWRTFREE_LOG_RES(nmp), 0, 0, 0)))
-			goto error_exit;
+			break;
 		/*
 		 * Lock out other callers by grabbing the bitmap inode lock.
 		 */
 		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
 						XFS_ILOCK_EXCL, &ip)))
-			goto error_exit;
+			break;
 		ASSERT(ip == mp->m_rbmip);
 		/*
 		 * Update the bitmap inode's size.
@@ -2038,7 +2037,7 @@
 		 */
 		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0,
 						XFS_ILOCK_EXCL, &ip)))
-			goto error_exit;
+			break;
 		ASSERT(ip == mp->m_rsumip);
 		/*
 		 * Update the summary inode's size.
@@ -2053,7 +2052,7 @@
 		    mp->m_rsumlevels != nmp->m_rsumlevels) {
 			error = xfs_rtcopy_summary(mp, nmp, tp);
 			if (error)
-				goto error_exit;
+				break;
 		}
 		/*
 		 * Update superblock fields.
@@ -2080,18 +2079,13 @@
 		error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
 			nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
 		if (error)
-			goto error_exit;
+			break;
 		/*
 		 * Mark more blocks free in the superblock.
 		 */
 		xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
 			nsbp->sb_rextents - sbp->sb_rextents);
 		/*
-		 * Free the fake mp structure.
-		 */
-		kmem_free(nmp, sizeof(*nmp));
-		nmp = NULL;
-		/*
 		 * Update mp values into the real mp structure.
 		 */
 		mp->m_rsumlevels = nrsumlevels;
@@ -2101,15 +2095,15 @@
 		 */
 		xfs_trans_commit(tp, 0, NULL);
 	}
-	return 0;
+
+	if (error)
+		xfs_trans_cancel(tp, cancelflags);
 
 	/*
-	 * Error paths come here.
+	 * Free the fake mp structure.
 	 */
-error_exit:
-	if (nmp)
-		kmem_free(nmp, sizeof(*nmp));
-	xfs_trans_cancel(tp, cancelflags);
+	kmem_free(nmp, sizeof(*nmp));
+
 	return error;
 }
 
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index bf168a9..467854b 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -60,10 +60,6 @@
 	 XFS_SB_VERSION_LOGV2BIT | \
 	 XFS_SB_VERSION_SECTORBIT | \
 	 XFS_SB_VERSION_MOREBITSBIT)
-#define	XFS_SB_VERSION_OKSASHBITS	\
-	(XFS_SB_VERSION_NUMBITS | \
-	 XFS_SB_VERSION_REALFBITS | \
-	 XFS_SB_VERSION_OKSASHFBITS)
 #define	XFS_SB_VERSION_OKREALBITS	\
 	(XFS_SB_VERSION_NUMBITS | \
 	 XFS_SB_VERSION_OKREALFBITS | \
@@ -81,9 +77,6 @@
 #define XFS_SB_VERSION2_RESERVED2BIT	0x00000002
 #define XFS_SB_VERSION2_RESERVED4BIT	0x00000004
 #define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
-#define XFS_SB_VERSION2_SASHFBITS	0xff000000	/* Mask: features that
-							   require changing
-							   PROM and SASH */
 
 #define	XFS_SB_VERSION2_OKREALFBITS	\
 	(XFS_SB_VERSION2_ATTR2BIT)
@@ -238,12 +231,6 @@
 }
 #endif /* __KERNEL__ */
 
-#define	XFS_SB_GOOD_SASH_VERSION(sbp)	\
-	((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \
-	  ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \
-	 ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
-	  !((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKSASHBITS)))
-
 #define	XFS_SB_VERSION_TONEW(v)	xfs_sb_version_tonew(v)
 static inline unsigned xfs_sb_version_tonew(unsigned v)
 {
@@ -461,15 +448,6 @@
  * File system sector to basic block conversions.
  */
 #define XFS_FSS_TO_BB(mp,sec)	((sec) << (mp)->m_sectbb_log)
-#define XFS_BB_TO_FSS(mp,bb)	\
-	(((bb) + (XFS_FSS_TO_BB(mp,1) - 1)) >> (mp)->m_sectbb_log)
-#define XFS_BB_TO_FSST(mp,bb)	((bb) >> (mp)->m_sectbb_log)
-
-/*
- * File system sector to byte conversions.
- */
-#define XFS_FSS_TO_B(mp,sectno)	((xfs_fsize_t)(sectno) << (mp)->m_sb.sb_sectlog)
-#define XFS_B_TO_FSST(mp,b)	(((__uint64_t)(b)) >> (mp)->m_sb.sb_sectlog)
 
 /*
  * File system block to basic block conversions.
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 9dc88b3..c68e001 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -149,7 +149,6 @@
 	void (*iop_unlock)(xfs_log_item_t *);
 	xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);
 	void (*iop_push)(xfs_log_item_t *);
-	void (*iop_abort)(xfs_log_item_t *);
 	void (*iop_pushbuf)(xfs_log_item_t *);
 	void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
 } xfs_item_ops_t;
@@ -163,7 +162,6 @@
 #define IOP_UNLOCK(ip)		(*(ip)->li_ops->iop_unlock)(ip)
 #define IOP_COMMITTED(ip, lsn)	(*(ip)->li_ops->iop_committed)(ip, lsn)
 #define IOP_PUSH(ip)		(*(ip)->li_ops->iop_push)(ip)
-#define IOP_ABORT(ip)		(*(ip)->li_ops->iop_abort)(ip)
 #define IOP_PUSHBUF(ip)		(*(ip)->li_ops->iop_pushbuf)(ip)
 #define IOP_COMMITTING(ip, lsn) (*(ip)->li_ops->iop_committing)(ip, lsn)
 
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 558c87f..fc39b16 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -276,7 +276,7 @@
 	xfs_mount_t	*mp,
 	xfs_log_item_t	*lip,
 	xfs_lsn_t	lsn,
-	unsigned long	s)
+	unsigned long	s) __releases(mp->m_ail_lock)
 {
 	xfs_ail_entry_t		*ailp;
 	xfs_log_item_t		*dlip=NULL;
@@ -328,7 +328,7 @@
 xfs_trans_delete_ail(
 	xfs_mount_t	*mp,
 	xfs_log_item_t	*lip,
-	unsigned long	s)
+	unsigned long	s) __releases(mp->m_ail_lock)
 {
 	xfs_ail_entry_t		*ailp;
 	xfs_log_item_t		*dlip;
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 13edab8..447ac43 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -46,11 +46,13 @@
 /*
  * From xfs_trans_ail.c
  */
-void			xfs_trans_update_ail(struct xfs_mount *,
-				     struct xfs_log_item *, xfs_lsn_t,
-				     unsigned long);
-void			xfs_trans_delete_ail(struct xfs_mount *,
-				     struct xfs_log_item *, unsigned long);
+void			xfs_trans_update_ail(struct xfs_mount *mp,
+				     struct xfs_log_item *lip, xfs_lsn_t lsn,
+				     unsigned long s)
+				     __releases(mp->m_ail_lock);
+void			xfs_trans_delete_ail(struct xfs_mount *mp,
+				     struct xfs_log_item *lip, unsigned long s)
+				     __releases(mp->m_ail_lock);
 struct xfs_log_item	*xfs_trans_first_ail(struct xfs_mount *, int *);
 struct xfs_log_item	*xfs_trans_next_ail(struct xfs_mount *,
 				     struct xfs_log_item *, int *, int *);
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index a34796e..62336a4 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -1922,7 +1922,7 @@
 	}
 
 	if (mp->m_flags & XFS_MOUNT_IHASHSIZE)
-		seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
+		seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", (int)mp->m_ihsize);
 
 	if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
 		seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 23cfa58..061e2ff 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -2366,10 +2366,15 @@
 
 	namelen = VNAMELEN(dentry);
 
+	if (!xfs_get_dir_entry(dentry, &ip)) {
+	        dm_di_mode = ip->i_d.di_mode;
+		IRELE(ip);
+	}
+
 	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
 		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp,
 					DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
-					name, NULL, 0, 0, 0);
+					name, NULL, dm_di_mode, 0, 0);
 		if (error)
 			return error;
 	}
@@ -2995,7 +3000,7 @@
 	int			cancel_flags;
 	int			committed;
 	bhv_vnode_t		*dir_vp;
-	int			dm_di_mode = 0;
+	int			dm_di_mode = S_IFDIR;
 	int			last_cdp_link;
 	int			namelen;
 	uint			resblks;
@@ -3010,11 +3015,16 @@
 		return XFS_ERROR(EIO);
 	namelen = VNAMELEN(dentry);
 
+	if (!xfs_get_dir_entry(dentry, &cdp)) {
+	        dm_di_mode = cdp->i_d.di_mode;
+		IRELE(cdp);
+	}
+
 	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
 		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
 					dir_vp, DM_RIGHT_NULL,
 					NULL, DM_RIGHT_NULL,
-					name, NULL, 0, 0, 0);
+					name, NULL, dm_di_mode, 0, 0);
 		if (error)
 			return XFS_ERROR(error);
 	}
@@ -3834,7 +3844,9 @@
 		XFS_MOUNT_ILOCK(mp);
 		vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
 		list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
+		spin_lock(&ip->i_flags_lock);
 		ip->i_flags |= XFS_IRECLAIMABLE;
+		spin_unlock(&ip->i_flags_lock);
 		XFS_MOUNT_IUNLOCK(mp);
 	}
 	return 0;
@@ -3859,8 +3871,10 @@
 	 * us.
 	 */
 	write_lock(&ih->ih_lock);
+	spin_lock(&ip->i_flags_lock);
 	if ((ip->i_flags & XFS_IRECLAIM) ||
 	    (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
+		spin_unlock(&ip->i_flags_lock);
 		write_unlock(&ih->ih_lock);
 		if (locked) {
 			xfs_ifunlock(ip);
@@ -3869,6 +3883,7 @@
 		return 1;
 	}
 	ip->i_flags |= XFS_IRECLAIM;
+	spin_unlock(&ip->i_flags_lock);
 	write_unlock(&ih->ih_lock);
 
 	/*
@@ -4272,7 +4287,7 @@
 	xfs_mount_t		*mp;
 	int			nimap;
 	uint			resblks;
-	int			rounding;
+	uint			rounding;
 	int			rt;
 	xfs_fileoff_t		startoffset_fsb;
 	xfs_trans_t		*tp;
@@ -4313,8 +4328,7 @@
 		vn_iowait(vp);	/* wait for the completion of any pending DIOs */
 	}
 
-	rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
-			(__uint8_t)NBPP);
+	rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, NBPP);
 	ilen = len + (offset & (rounding - 1));
 	ioffset = offset & ~(rounding - 1);
 	if (ilen & (rounding - 1))
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91rm9200/at91rm9200.h
index 58f4093..a5a86b1 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200.h
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200.h
@@ -19,67 +19,80 @@
 /*
  * Peripheral identifiers/interrupts.
  */
-#define AT91_ID_FIQ	0	/* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS	1	/* System Peripheral */
-#define AT91_ID_PIOA	2	/* Parallel IO Controller A */
-#define AT91_ID_PIOB	3	/* Parallel IO Controller B */
-#define AT91_ID_PIOC	4	/* Parallel IO Controller C */
-#define AT91_ID_PIOD	5	/* Parallel IO Controller D */
-#define AT91_ID_US0	6	/* USART 0 */
-#define AT91_ID_US1	7	/* USART 1 */
-#define AT91_ID_US2	8	/* USART 2 */
-#define AT91_ID_US3	9	/* USART 3 */
-#define AT91_ID_MCI	10	/* Multimedia Card Interface */
-#define AT91_ID_UDP	11	/* USB Device Port */
-#define AT91_ID_TWI	12	/* Two-Wire Interface */
-#define AT91_ID_SPI	13	/* Serial Peripheral Interface */
-#define AT91_ID_SSC0	14	/* Serial Synchronous Controller 0 */
-#define AT91_ID_SSC1	15	/* Serial Synchronous Controller 1 */
-#define AT91_ID_SSC2	16	/* Serial Synchronous Controller 2 */
-#define AT91_ID_TC0	17	/* Timer Counter 0 */
-#define AT91_ID_TC1	18	/* Timer Counter 1 */
-#define AT91_ID_TC2	19	/* Timer Counter 2 */
-#define AT91_ID_TC3	20	/* Timer Counter 3 */
-#define AT91_ID_TC4	21	/* Timer Counter 4 */
-#define AT91_ID_TC5	22	/* Timer Counter 5 */
-#define AT91_ID_UHP	23	/* USB Host port */
-#define AT91_ID_EMAC	24	/* Ethernet MAC */
-#define AT91_ID_IRQ0	25	/* Advanced Interrupt Controller (IRQ0) */
-#define AT91_ID_IRQ1	26	/* Advanced Interrupt Controller (IRQ1) */
-#define AT91_ID_IRQ2	27	/* Advanced Interrupt Controller (IRQ2) */
-#define AT91_ID_IRQ3	28	/* Advanced Interrupt Controller (IRQ3) */
-#define AT91_ID_IRQ4	29	/* Advanced Interrupt Controller (IRQ4) */
-#define AT91_ID_IRQ5	30	/* Advanced Interrupt Controller (IRQ5) */
-#define AT91_ID_IRQ6	31	/* Advanced Interrupt Controller (IRQ6) */
+#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS		1	/* System Peripheral */
+#define AT91RM9200_ID_PIOA	2	/* Parallel IO Controller A */
+#define AT91RM9200_ID_PIOB	3	/* Parallel IO Controller B */
+#define AT91RM9200_ID_PIOC	4	/* Parallel IO Controller C */
+#define AT91RM9200_ID_PIOD	5	/* Parallel IO Controller D */
+#define AT91RM9200_ID_US0	6	/* USART 0 */
+#define AT91RM9200_ID_US1	7	/* USART 1 */
+#define AT91RM9200_ID_US2	8	/* USART 2 */
+#define AT91RM9200_ID_US3	9	/* USART 3 */
+#define AT91RM9200_ID_MCI	10	/* Multimedia Card Interface */
+#define AT91RM9200_ID_UDP	11	/* USB Device Port */
+#define AT91RM9200_ID_TWI	12	/* Two-Wire Interface */
+#define AT91RM9200_ID_SPI	13	/* Serial Peripheral Interface */
+#define AT91RM9200_ID_SSC0	14	/* Serial Synchronous Controller 0 */
+#define AT91RM9200_ID_SSC1	15	/* Serial Synchronous Controller 1 */
+#define AT91RM9200_ID_SSC2	16	/* Serial Synchronous Controller 2 */
+#define AT91RM9200_ID_TC0	17	/* Timer Counter 0 */
+#define AT91RM9200_ID_TC1	18	/* Timer Counter 1 */
+#define AT91RM9200_ID_TC2	19	/* Timer Counter 2 */
+#define AT91RM9200_ID_TC3	20	/* Timer Counter 3 */
+#define AT91RM9200_ID_TC4	21	/* Timer Counter 4 */
+#define AT91RM9200_ID_TC5	22	/* Timer Counter 5 */
+#define AT91RM9200_ID_UHP	23	/* USB Host port */
+#define AT91RM9200_ID_EMAC	24	/* Ethernet MAC */
+#define AT91RM9200_ID_IRQ0	25	/* Advanced Interrupt Controller (IRQ0) */
+#define AT91RM9200_ID_IRQ1	26	/* Advanced Interrupt Controller (IRQ1) */
+#define AT91RM9200_ID_IRQ2	27	/* Advanced Interrupt Controller (IRQ2) */
+#define AT91RM9200_ID_IRQ3	28	/* Advanced Interrupt Controller (IRQ3) */
+#define AT91RM9200_ID_IRQ4	29	/* Advanced Interrupt Controller (IRQ4) */
+#define AT91RM9200_ID_IRQ5	30	/* Advanced Interrupt Controller (IRQ5) */
+#define AT91RM9200_ID_IRQ6	31	/* Advanced Interrupt Controller (IRQ6) */
 
 
 /*
  * Peripheral physical base addresses.
  */
-#define AT91_BASE_TCB0		0xfffa0000
-#define AT91_BASE_TC0		0xfffa0000
-#define AT91_BASE_TC1		0xfffa0040
-#define AT91_BASE_TC2		0xfffa0080
-#define AT91_BASE_TCB1		0xfffa4000
-#define AT91_BASE_TC3		0xfffa4000
-#define AT91_BASE_TC4		0xfffa4040
-#define AT91_BASE_TC5		0xfffa4080
-#define AT91_BASE_UDP		0xfffb0000
-#define AT91_BASE_MCI		0xfffb4000
-#define AT91_BASE_TWI		0xfffb8000
-#define AT91_BASE_EMAC		0xfffbc000
-#define AT91_BASE_US0		0xfffc0000
-#define AT91_BASE_US1		0xfffc4000
-#define AT91_BASE_US2		0xfffc8000
-#define AT91_BASE_US3		0xfffcc000
-#define AT91_BASE_SSC0		0xfffd0000
-#define AT91_BASE_SSC1		0xfffd4000
-#define AT91_BASE_SSC2		0xfffd8000
-#define AT91_BASE_SPI		0xfffe0000
+#define AT91RM9200_BASE_TCB0	0xfffa0000
+#define AT91RM9200_BASE_TC0	0xfffa0000
+#define AT91RM9200_BASE_TC1	0xfffa0040
+#define AT91RM9200_BASE_TC2	0xfffa0080
+#define AT91RM9200_BASE_TCB1	0xfffa4000
+#define AT91RM9200_BASE_TC3	0xfffa4000
+#define AT91RM9200_BASE_TC4	0xfffa4040
+#define AT91RM9200_BASE_TC5	0xfffa4080
+#define AT91RM9200_BASE_UDP	0xfffb0000
+#define AT91RM9200_BASE_MCI	0xfffb4000
+#define AT91RM9200_BASE_TWI	0xfffb8000
+#define AT91RM9200_BASE_EMAC	0xfffbc000
+#define AT91RM9200_BASE_US0	0xfffc0000
+#define AT91RM9200_BASE_US1	0xfffc4000
+#define AT91RM9200_BASE_US2	0xfffc8000
+#define AT91RM9200_BASE_US3	0xfffcc000
+#define AT91RM9200_BASE_SSC0	0xfffd0000
+#define AT91RM9200_BASE_SSC1	0xfffd4000
+#define AT91RM9200_BASE_SSC2	0xfffd8000
+#define AT91RM9200_BASE_SPI	0xfffe0000
 #define AT91_BASE_SYS		0xfffff000
 
 
 /*
+ * Internal Memory.
+ */
+#define AT91RM9200_ROM_BASE	0x00100000	/* Internal ROM base address */
+#define AT91RM9200_ROM_SIZE	SZ_128K		/* Internal ROM size (128Kb) */
+
+#define AT91RM9200_SRAM_BASE	0x00200000	/* Internal SRAM base address */
+#define AT91RM9200_SRAM_SIZE	SZ_16K		/* Internal SRAM size (16Kb) */
+
+#define AT91RM9200_UHP_BASE	0x00300000	/* USB Host controller */
+
+
+#if 0
+/*
  * PIO pin definitions (peripheral A/B multiplexing).
  */
 #define AT91_PA0_MISO		(1 <<  0)	/* A: SPI Master-In Slave-Out */
@@ -257,5 +270,6 @@
 #define AT91_PD25_TPK13		(1 << 25)	/* B: ETM Trace Packet Port 13 */
 #define AT91_PD26_TPK14		(1 << 26)	/* B: ETM Trace Packet Port 14 */
 #define AT91_PD27_TPK15		(1 << 27)	/* B: ETM Trace Packet Port 15 */
+#endif
 
 #endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
index 0f4c12d..73693fe 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
@@ -80,6 +80,9 @@
 #define		AT91_CIDR_NVPTYP	(7    << 28)		/* Nonvolatile Program Memory Type */
 #define		AT91_CIDR_EXT		(1    << 31)		/* Extension Flag */
 
+#define AT91_AIC_FFER		(AT91_AIC + 0x140)	/* Fast Forcing Enable Register [SAM9 only] */
+#define AT91_AIC_FFDR		(AT91_AIC + 0x144)	/* Fast Forcing Disable Register [SAM9 only] */
+#define AT91_AIC_FFSR		(AT91_AIC + 0x148)	/* Fast Forcing Status Register [SAM9 only] */
 
 /*
  * PIO Controllers.
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h
new file mode 100644
index 0000000..93547d7
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h
@@ -0,0 +1,57 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_twi.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Two-wire Interface (TWI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * 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 AT91RM9200_TWI_H
+#define AT91RM9200_TWI_H
+
+#define	AT91_TWI_CR		0x00		/* Control Register */
+#define		AT91_TWI_START		(1 <<  0)	/* Send a Start Condition */
+#define		AT91_TWI_STOP		(1 <<  1)	/* Send a Stop Condition */
+#define		AT91_TWI_MSEN		(1 <<  2)	/* Master Transfer Enable */
+#define		AT91_TWI_MSDIS		(1 <<  3)	/* Master Transfer Disable */
+#define		AT91_TWI_SWRST		(1 <<  7)	/* Software Reset */
+
+#define	AT91_TWI_MMR		0x04		/* Master Mode Register */
+#define		AT91_TWI_IADRSZ		(3    <<  8)	/* Internal Device Address Size */
+#define			AT91_TWI_IADRSZ_NO		(0 << 8)
+#define			AT91_TWI_IADRSZ_1		(1 << 8)
+#define			AT91_TWI_IADRSZ_2		(2 << 8)
+#define			AT91_TWI_IADRSZ_3		(3 << 8)
+#define		AT91_TWI_MREAD		(1    << 12)	/* Master Read Direction */
+#define		AT91_TWI_DADR		(0x7f << 16)	/* Device Address */
+
+#define	AT91_TWI_IADR		0x0c		/* Internal Address Register */
+
+#define	AT91_TWI_CWGR		0x10		/* Clock Waveform Generator Register */
+#define		AT91_TWI_CLDIV		(0xff <<  0)	/* Clock Low Divisor */
+#define		AT91_TWI_CHDIV		(0xff <<  8)	/* Clock High Divisor */
+#define		AT91_TWI_CKDIV		(7    << 16)	/* Clock Divider */
+
+#define	AT91_TWI_SR		0x20		/* Status Register */
+#define		AT91_TWI_TXCOMP		(1 <<  0)	/* Transmission Complete */
+#define		AT91_TWI_RXRDY		(1 <<  1)	/* Receive Holding Register Ready */
+#define		AT91_TWI_TXRDY		(1 <<  2)	/* Transmit Holding Register Ready */
+#define		AT91_TWI_OVRE		(1 <<  6)	/* Overrun Error */
+#define		AT91_TWI_UNRE		(1 <<  7)	/* Underrun Error */
+#define		AT91_TWI_NACK		(1 <<  8)	/* Not Acknowledged */
+
+#define	AT91_TWI_IER		0x24		/* Interrupt Enable Register */
+#define	AT91_TWI_IDR		0x28		/* Interrupt Disable Register */
+#define	AT91_TWI_IMR		0x2c		/* Interrupt Mask Register */
+#define	AT91_TWI_RHR		0x30		/* Receive Holding Register */
+#define	AT91_TWI_THR		0x34		/* Transmit Holding Register */
+
+#endif
+
diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h
index dbde1ba..a011d27 100644
--- a/include/asm-arm/arch-at91rm9200/gpio.h
+++ b/include/asm-arm/arch-at91rm9200/gpio.h
@@ -17,10 +17,9 @@
 
 #define PIN_BASE		NR_AIC_IRQS
 
-#define PQFP_GPIO_BANKS		3	/* PQFP package has 3 banks */
-#define BGA_GPIO_BANKS		4	/* BGA package has 4 banks */
+#define MAX_GPIO_BANKS		4
 
-/* these pin numbers double as IRQ numbers, like AT91_ID_* values */
+/* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
 
 #define	AT91_PIN_PA0	(PIN_BASE + 0x00 + 0)
 #define	AT91_PIN_PA1	(PIN_BASE + 0x00 + 1)
@@ -180,17 +179,18 @@
 
 #ifndef __ASSEMBLY__
 /* setup setup routines, called from board init or driver probe() */
-extern int at91_set_A_periph(unsigned pin, int use_pullup);
-extern int at91_set_B_periph(unsigned pin, int use_pullup);
-extern int at91_set_gpio_input(unsigned pin, int use_pullup);
-extern int at91_set_gpio_output(unsigned pin, int value);
-extern int at91_set_deglitch(unsigned pin, int is_on);
-extern int at91_set_multi_drive(unsigned pin, int is_on);
+extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_gpio_output(unsigned pin, int value);
+extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on);
+extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on);
 
 /* callable at any time */
 extern int at91_set_gpio_value(unsigned pin, int value);
 extern int at91_get_gpio_value(unsigned pin);
 
+/* callable only from core power-management code */
 extern void at91_gpio_suspend(void);
 extern void at91_gpio_resume(void);
 #endif
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h
index 235d39d..6551b4d 100644
--- a/include/asm-arm/arch-at91rm9200/hardware.h
+++ b/include/asm-arm/arch-at91rm9200/hardware.h
@@ -34,27 +34,14 @@
  * Virtual to Physical Address mapping for IO devices.
  */
 #define AT91_VA_BASE_SYS	AT91_IO_P2V(AT91_BASE_SYS)
-#define AT91_VA_BASE_SPI	AT91_IO_P2V(AT91_BASE_SPI)
-#define AT91_VA_BASE_SSC2	AT91_IO_P2V(AT91_BASE_SSC2)
-#define AT91_VA_BASE_SSC1	AT91_IO_P2V(AT91_BASE_SSC1)
-#define AT91_VA_BASE_SSC0	AT91_IO_P2V(AT91_BASE_SSC0)
-#define AT91_VA_BASE_US3	AT91_IO_P2V(AT91_BASE_US3)
-#define AT91_VA_BASE_US2	AT91_IO_P2V(AT91_BASE_US2)
-#define AT91_VA_BASE_US1	AT91_IO_P2V(AT91_BASE_US1)
-#define AT91_VA_BASE_US0	AT91_IO_P2V(AT91_BASE_US0)
-#define AT91_VA_BASE_EMAC	AT91_IO_P2V(AT91_BASE_EMAC)
-#define AT91_VA_BASE_TWI	AT91_IO_P2V(AT91_BASE_TWI)
-#define AT91_VA_BASE_MCI	AT91_IO_P2V(AT91_BASE_MCI)
-#define AT91_VA_BASE_UDP	AT91_IO_P2V(AT91_BASE_UDP)
-#define AT91_VA_BASE_TCB1	AT91_IO_P2V(AT91_BASE_TCB1)
-#define AT91_VA_BASE_TCB0	AT91_IO_P2V(AT91_BASE_TCB0)
-
-/* Internal SRAM */
-#define AT91_SRAM_BASE		0x00200000	/* Internal SRAM base address */
-#define AT91_SRAM_SIZE		0x00004000	/* Internal SRAM SIZE (16Kb) */
+#define AT91_VA_BASE_SPI	AT91_IO_P2V(AT91RM9200_BASE_SPI)
+#define AT91_VA_BASE_EMAC	AT91_IO_P2V(AT91RM9200_BASE_EMAC)
+#define AT91_VA_BASE_TWI	AT91_IO_P2V(AT91RM9200_BASE_TWI)
+#define AT91_VA_BASE_MCI	AT91_IO_P2V(AT91RM9200_BASE_MCI)
+#define AT91_VA_BASE_UDP	AT91_IO_P2V(AT91RM9200_BASE_UDP)
 
  /* Internal SRAM is mapped below the IO devices */
-#define AT91_SRAM_VIRT_BASE	(AT91_IO_VIRT_BASE - AT91_SRAM_SIZE)
+#define AT91_SRAM_VIRT_BASE	(AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE)
 
 /* Serial ports */
 #define AT91_NR_UART		5		/* 4 USART3's and one DBGU port */
@@ -71,9 +58,6 @@
 /* Compact Flash */
 #define AT91_CF_BASE		0x50000000	/* NCS4-NCS6: Compact Flash physical base address */
 
-/* Multi-Master Memory controller */
-#define AT91_UHP_BASE		0x00300000	/* USB Host controller */
-
 /* Clocks */
 #define AT91_SLOW_CLOCK		32768		/* slow clock */
 
diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91rm9200/irqs.h
index f63842c..763cb96 100644
--- a/include/asm-arm/arch-at91rm9200/irqs.h
+++ b/include/asm-arm/arch-at91rm9200/irqs.h
@@ -32,7 +32,7 @@
 
 
 /*
- * IRQ interrupt symbols are the AT91_ID_* symbols in at91rm9200.h
+ * IRQ interrupt symbols are the AT91xxx_ID_* symbols
  * for IRQs handled directly through the AIC, or else the AT91_PIN_*
  * symbols in gpio.h for ones handled indirectly as GPIOs.
  * We make provision for 4 banks of GPIO.
diff --git a/include/asm-arm/arch-clps711x/time.h b/include/asm-arm/arch-clps711x/time.h
index 9cb27cd..0e4a390 100644
--- a/include/asm-arm/arch-clps711x/time.h
+++ b/include/asm-arm/arch-clps711x/time.h
@@ -29,7 +29,7 @@
 p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	do_leds();
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/include/asm-arm/arch-iop32x/debug-macro.S b/include/asm-arm/arch-iop32x/debug-macro.S
new file mode 100644
index 0000000..9022b68
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/debug-macro.S
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-iop32x/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ */
+
+		.macro	addruart, rx
+		mov	\rx, #0xfe000000	@ physical as well as virtual
+		orr	\rx, \rx, #0x00800000	@ location of the UART
+		.endm
+
+#define UART_SHIFT	0
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-iop3xx/dma.h b/include/asm-arm/arch-iop32x/dma.h
similarity index 71%
rename from include/asm-arm/arch-iop3xx/dma.h
rename to include/asm-arm/arch-iop32x/dma.h
index 1e808db..e977a9e 100644
--- a/include/asm-arm/arch-iop3xx/dma.h
+++ b/include/asm-arm/arch-iop32x/dma.h
@@ -1,7 +1,7 @@
 /*
- * linux/include/asm-arm/arch-iop3xx/dma.h
+ * include/asm-arm/arch-iop32x/dma.h
  *
- *  Copyright (C) 2004 Intel Corp.
+ * Copyright (C) 2004 Intel Corp.
  *
  * 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
diff --git a/include/asm-arm/arch-iop32x/entry-macro.S b/include/asm-arm/arch-iop32x/entry-macro.S
new file mode 100644
index 0000000..1500cbb
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/entry-macro.S
@@ -0,0 +1,21 @@
+/*
+ * include/asm-arm/arch-iop32x/entry-macro.S
+ *
+ * Low-level IRQ helper macros for IOP32x-based platforms
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <asm/arch/iop32x.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\base, =IOP3XX_REG_ADDR(0x07D8)
+		ldr	\irqstat, [\base]		@ Read IINTSRC
+		cmp	\irqstat, #0
+		clzne	\irqnr, \irqstat
+		rsbne	\irqnr, \irqnr, #31
+		.endm
diff --git a/include/asm-arm/arch-iop32x/glantank.h b/include/asm-arm/arch-iop32x/glantank.h
new file mode 100644
index 0000000..3b06561
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/glantank.h
@@ -0,0 +1,13 @@
+/*
+ * include/asm/arch-iop32x/glantank.h
+ *
+ * IO-Data GLAN Tank board registers
+ */
+
+#ifndef __GLANTANK_H
+#define __GLANTANK_H
+
+#define GLANTANK_UART		0xfe800000	/* UART */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/hardware.h b/include/asm-arm/arch-iop32x/hardware.h
new file mode 100644
index 0000000..6556ed5
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/hardware.h
@@ -0,0 +1,44 @@
+/*
+ * include/asm-arm/arch-iop32x/hardware.h
+ */
+
+#ifndef __HARDWARE_H
+#define __HARDWARE_H
+
+#include <asm/types.h>
+
+/*
+ * Note about PCI IO space mappings
+ *
+ * To make IO space accesses efficient, we store virtual addresses in
+ * the IO resources.
+ *
+ * The PCI IO space is located at virtual 0xfe000000 from physical
+ * 0x90000000. The PCI BARs must be programmed with physical addresses,
+ * but when we read them, we convert them to virtual addresses. See
+ * arch/arm/plat-iop/pci.c.
+ */
+#define pcibios_assign_all_busses() 1
+#define PCIBIOS_MIN_IO		0x00000000
+#define PCIBIOS_MIN_MEM		0x00000000
+
+#ifndef __ASSEMBLY__
+void iop32x_init_irq(void);
+#endif
+
+
+/*
+ * Generic chipset bits
+ */
+#include "iop32x.h"
+
+/*
+ * Board specific bits
+ */
+#include "glantank.h"
+#include "iq80321.h"
+#include "iq31244.h"
+#include "n2100.h"
+
+
+#endif
diff --git a/include/asm-arm/arch-iop3xx/io.h b/include/asm-arm/arch-iop32x/io.h
similarity index 62%
copy from include/asm-arm/arch-iop3xx/io.h
copy to include/asm-arm/arch-iop32x/io.h
index 36adbdf..12d9ee0 100644
--- a/include/asm-arm/arch-iop3xx/io.h
+++ b/include/asm-arm/arch-iop32x/io.h
@@ -1,21 +1,22 @@
 /*
- * linux/include/asm-arm/arch-iop3xx/io.h
+ * include/asm-arm/arch-iop32x/io.h
  *
- *  Copyright (C) 2001  MontaVista Software, Inc.
+ * Copyright (C) 2001 MontaVista Software, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
+#ifndef __IO_H
+#define __IO_H
 
 #include <asm/hardware.h>
 
-#define IO_SPACE_LIMIT 0xffffffff
+#define IO_SPACE_LIMIT		0xffffffff
 
 #define __io(p)			((void __iomem *)(p))
 #define __mem_pci(a)		(a)
 
+
 #endif
diff --git a/include/asm-arm/arch-iop32x/iop32x.h b/include/asm-arm/arch-iop32x/iop32x.h
new file mode 100644
index 0000000..4bbd85f
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/iop32x.h
@@ -0,0 +1,28 @@
+/*
+ * include/asm-arm/arch-iop32x/iop32x.h
+ *
+ * Intel IOP32X Chip definitions
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __IOP32X_H
+#define __IOP32X_H
+
+/*
+ * Peripherals that are shared between the iop32x and iop33x but
+ * located at different addresses.
+ */
+#define IOP3XX_GPIO_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x07c0 + (reg))
+#define IOP3XX_TIMER_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
+
+#include <asm/hardware/iop3xx.h>
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/iq31244.h b/include/asm-arm/arch-iop32x/iq31244.h
new file mode 100644
index 0000000..fff4eaf
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/iq31244.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-arm/arch-iop32x/iq31244.h
+ *
+ * Intel IQ31244 evaluation board registers
+ */
+
+#ifndef __IQ31244_H
+#define __IQ31244_H
+
+#define IQ31244_UART		0xfe800000	/* UART #1 */
+#define IQ31244_7SEG_1		0xfe840000	/* 7-Segment MSB */
+#define IQ31244_7SEG_0		0xfe850000	/* 7-Segment LSB (WO) */
+#define IQ31244_ROTARY_SW	0xfe8d0000	/* Rotary Switch */
+#define IQ31244_BATT_STAT	0xfe8f0000	/* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/iq80321.h b/include/asm-arm/arch-iop32x/iq80321.h
new file mode 100644
index 0000000..eb69db9
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/iq80321.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-arm/arch-iop32x/iq80321.h
+ *
+ * Intel IQ80321 evaluation board registers
+ */
+
+#ifndef __IQ80321_H
+#define __IQ80321_H
+
+#define IQ80321_UART		0xfe800000	/* UART #1 */
+#define IQ80321_7SEG_1		0xfe840000	/* 7-Segment MSB */
+#define IQ80321_7SEG_0		0xfe850000	/* 7-Segment LSB (WO) */
+#define IQ80321_ROTARY_SW	0xfe8d0000	/* Rotary Switch */
+#define IQ80321_BATT_STAT	0xfe8f0000	/* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/irqs.h b/include/asm-arm/arch-iop32x/irqs.h
new file mode 100644
index 0000000..bbaef87
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/irqs.h
@@ -0,0 +1,50 @@
+/*
+ * include/asm-arm/arch-iop32x/irqs.h
+ *
+ * Author:	Rory Bolt <rorybolt@pacbell.net>
+ * Copyright:	(C) 2002 Rory Bolt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __IRQS_H
+#define __IRQS_H
+
+/*
+ * IOP80321 chipset interrupts
+ */
+#define IRQ_IOP32X_DMA0_EOT	0
+#define IRQ_IOP32X_DMA0_EOC	1
+#define IRQ_IOP32X_DMA1_EOT	2
+#define IRQ_IOP32X_DMA1_EOC	3
+#define IRQ_IOP32X_AA_EOT	6
+#define IRQ_IOP32X_AA_EOC	7
+#define IRQ_IOP32X_CORE_PMON	8
+#define IRQ_IOP32X_TIMER0	9
+#define IRQ_IOP32X_TIMER1	10
+#define IRQ_IOP32X_I2C_0	11
+#define IRQ_IOP32X_I2C_1	12
+#define IRQ_IOP32X_MESSAGING	13
+#define IRQ_IOP32X_ATU_BIST	14
+#define IRQ_IOP32X_PERFMON	15
+#define IRQ_IOP32X_CORE_PMU	16
+#define IRQ_IOP32X_BIU_ERR	17
+#define IRQ_IOP32X_ATU_ERR	18
+#define IRQ_IOP32X_MCU_ERR	19
+#define IRQ_IOP32X_DMA0_ERR	20
+#define IRQ_IOP32X_DMA1_ERR	21
+#define IRQ_IOP32X_AA_ERR	23
+#define IRQ_IOP32X_MSG_ERR	24
+#define IRQ_IOP32X_SSP		25
+#define IRQ_IOP32X_XINT0	27
+#define IRQ_IOP32X_XINT1	28
+#define IRQ_IOP32X_XINT2	29
+#define IRQ_IOP32X_XINT3	30
+#define IRQ_IOP32X_HPI		31
+
+#define NR_IRQS			32
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/memory.h b/include/asm-arm/arch-iop32x/memory.h
new file mode 100644
index 0000000..764cd3f
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/memory.h
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-iop32x/memory.h
+ */
+
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+#include <asm/hardware.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	UL(0xa0000000)
+
+/*
+ * Virtual view <-> PCI DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *		address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *		to an address that the kernel can use.
+ */
+#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
+#define __bus_to_virt(x)	(__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/n2100.h b/include/asm-arm/arch-iop32x/n2100.h
new file mode 100644
index 0000000..fed31a6
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/n2100.h
@@ -0,0 +1,19 @@
+/*
+ * include/asm/arch-iop32x/n2100.h
+ *
+ * Thecus N2100 board registers
+ */
+
+#ifndef __N2100_H
+#define __N2100_H
+
+#define N2100_UART		0xfe800000	/* UART */
+
+#define N2100_COPY_BUTTON	IOP3XX_GPIO_LINE(0)
+#define N2100_PCA9532_RESET	IOP3XX_GPIO_LINE(2)
+#define N2100_RESET_BUTTON	IOP3XX_GPIO_LINE(3)
+#define N2100_HARDWARE_RESET	IOP3XX_GPIO_LINE(4)
+#define N2100_POWER_BUTTON	IOP3XX_GPIO_LINE(5)
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/system.h b/include/asm-arm/arch-iop32x/system.h
new file mode 100644
index 0000000..17b7eb7
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/system.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-iop32x/system.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	local_irq_disable();
+
+	if (machine_is_n2100()) {
+		gpio_line_set(N2100_HARDWARE_RESET, GPIO_LOW);
+		gpio_line_config(N2100_HARDWARE_RESET, GPIO_OUT);
+		while (1)
+			;
+	}
+
+	*IOP3XX_PCSR = 0x30;
+
+	/* Jump into ROM at address 0 */
+	cpu_reset(0);
+}
diff --git a/include/asm-arm/arch-iop32x/timex.h b/include/asm-arm/arch-iop32x/timex.h
new file mode 100644
index 0000000..9934b08
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/timex.h
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-iop32x/timex.h
+ *
+ * IOP32x architecture timex specifications
+ */
+
+#include <asm/hardware.h>
+
+#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/include/asm-arm/arch-iop32x/uncompress.h b/include/asm-arm/arch-iop32x/uncompress.h
new file mode 100644
index 0000000..e64f52b
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/uncompress.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-iop32x/uncompress.h
+ */
+
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <linux/serial_reg.h>
+#include <asm/hardware.h>
+
+static volatile u8 *uart_base;
+
+#define TX_DONE		(UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void putc(char c)
+{
+	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+		barrier();
+	uart_base[UART_TX] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+	if (machine_is_iq80321())
+		uart_base = (volatile u8 *)IQ80321_UART;
+	else if (machine_is_iq31244())
+		uart_base = (volatile u8 *)IQ31244_UART;
+	else
+		uart_base = (volatile u8 *)0xfe800000;
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop32x/vmalloc.h b/include/asm-arm/arch-iop32x/vmalloc.h
new file mode 100644
index 0000000..0a70baa
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/vmalloc.h
@@ -0,0 +1,5 @@
+/*
+ * include/asm-arm/arch-iop32x/vmalloc.h
+ */
+
+#define VMALLOC_END	0xfe000000
diff --git a/include/asm-arm/arch-iop33x/debug-macro.S b/include/asm-arm/arch-iop33x/debug-macro.S
new file mode 100644
index 0000000..9e7132e
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/debug-macro.S
@@ -0,0 +1,24 @@
+/*
+ * include/asm-arm/arch-iop33x/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ */
+
+		.macro	addruart, rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ mmu enabled?
+		moveq	\rx, #0xff000000	@ physical
+		movne	\rx, #0xfe000000	@ virtual
+		orr	\rx, \rx, #0x00ff0000
+		orr	\rx, \rx, #0x0000f700
+		.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-iop3xx/dma.h b/include/asm-arm/arch-iop33x/dma.h
similarity index 71%
copy from include/asm-arm/arch-iop3xx/dma.h
copy to include/asm-arm/arch-iop33x/dma.h
index 1e808db..b7775fd 100644
--- a/include/asm-arm/arch-iop3xx/dma.h
+++ b/include/asm-arm/arch-iop33x/dma.h
@@ -1,7 +1,7 @@
 /*
- * linux/include/asm-arm/arch-iop3xx/dma.h
+ * include/asm-arm/arch-iop33x/dma.h
  *
- *  Copyright (C) 2004 Intel Corp.
+ * Copyright (C) 2004 Intel Corp.
  *
  * 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
diff --git a/include/asm-arm/arch-iop33x/entry-macro.S b/include/asm-arm/arch-iop33x/entry-macro.S
new file mode 100644
index 0000000..92b7917
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/entry-macro.S
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-iop33x/entry-macro.S
+ *
+ * Low-level IRQ helper macros for IOP33x-based platforms
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <asm/arch/iop33x.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\base, =IOP3XX_REG_ADDR(0x07C8)
+		ldr	\irqstat, [\base]		@ Read IINTVEC
+		cmp	\irqstat, #0
+		ldreq	\irqstat, [\base]		@ erratum 63 workaround
+		adds	\irqnr, \irqstat, #1
+		movne	\irqnr, \irqstat, lsr #2
+		.endm
diff --git a/include/asm-arm/arch-iop33x/hardware.h b/include/asm-arm/arch-iop33x/hardware.h
new file mode 100644
index 0000000..0659cf9
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/hardware.h
@@ -0,0 +1,46 @@
+/*
+ * include/asm-arm/arch-iop33x/hardware.h
+ */
+
+#ifndef __HARDWARE_H
+#define __HARDWARE_H
+
+#include <asm/types.h>
+
+/*
+ * Note about PCI IO space mappings
+ *
+ * To make IO space accesses efficient, we store virtual addresses in
+ * the IO resources.
+ *
+ * The PCI IO space is located at virtual 0xfe000000 from physical
+ * 0x90000000.  The PCI BARs must be programmed with physical addresses,
+ * but when we read them, we convert them to virtual addresses.  See
+ * arch/arm/mach-iop3xx/iop3xx-pci.c
+ */
+#define pcibios_assign_all_busses()	1
+#define PCIBIOS_MIN_IO		0x00000000
+#define PCIBIOS_MIN_MEM		0x00000000
+
+#ifndef __ASSEMBLY__
+void iop33x_init_irq(void);
+
+extern struct platform_device iop33x_uart0_device;
+extern struct platform_device iop33x_uart1_device;
+#endif
+
+
+/*
+ * Generic chipset bits
+ *
+ */
+#include "iop33x.h"
+
+/*
+ * Board specific bits
+ */
+#include "iq80331.h"
+#include "iq80332.h"
+
+
+#endif
diff --git a/include/asm-arm/arch-iop3xx/io.h b/include/asm-arm/arch-iop33x/io.h
similarity index 62%
rename from include/asm-arm/arch-iop3xx/io.h
rename to include/asm-arm/arch-iop33x/io.h
index 36adbdf..c017402 100644
--- a/include/asm-arm/arch-iop3xx/io.h
+++ b/include/asm-arm/arch-iop33x/io.h
@@ -1,21 +1,21 @@
 /*
- * linux/include/asm-arm/arch-iop3xx/io.h
+ * include/asm-arm/arch-iop33x/io.h
  *
- *  Copyright (C) 2001  MontaVista Software, Inc.
+ * Copyright (C) 2001  MontaVista Software, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
+#ifndef __IO_H
+#define __IO_H
 
 #include <asm/hardware.h>
 
-#define IO_SPACE_LIMIT 0xffffffff
-
+#define IO_SPACE_LIMIT		0xffffffff
 #define __io(p)			((void __iomem *)(p))
 #define __mem_pci(a)		(a)
 
+
 #endif
diff --git a/include/asm-arm/arch-iop33x/iop33x.h b/include/asm-arm/arch-iop33x/iop33x.h
new file mode 100644
index 0000000..7ac6e93
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/iop33x.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-iop33x/iop33x.h
+ *
+ * Intel IOP33X Chip definitions
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2003, 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __IOP33X_H
+#define __IOP33X_H
+
+/*
+ * Peripherals that are shared between the iop32x and iop33x but
+ * located at different addresses.
+ */
+#define IOP3XX_GPIO_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x1780 + (reg))
+#define IOP3XX_TIMER_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x07d0 + (reg))
+
+#include <asm/hardware/iop3xx.h>
+
+/* UARTs  */
+#define IOP33X_UART0_PHYS	(IOP3XX_PERIPHERAL_PHYS_BASE + 0x1700)
+#define IOP33X_UART0_VIRT	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x1700)
+#define IOP33X_UART1_PHYS	(IOP3XX_PERIPHERAL_PHYS_BASE + 0x1740)
+#define IOP33X_UART1_VIRT	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x1740)
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/iq80331.h b/include/asm-arm/arch-iop33x/iq80331.h
new file mode 100644
index 0000000..79b9302
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/iq80331.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/arch-iop33x/iq80331.h
+ *
+ * Intel IQ80331 evaluation board registers
+ */
+
+#ifndef __IQ80331_H
+#define __IQ80331_H
+
+#define IQ80331_7SEG_1		0xce840000	/* 7-Segment MSB */
+#define IQ80331_7SEG_0		0xce850000	/* 7-Segment LSB (WO) */
+#define IQ80331_ROTARY_SW	0xce8d0000	/* Rotary Switch */
+#define IQ80331_BATT_STAT	0xce8f0000	/* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/iq80332.h b/include/asm-arm/arch-iop33x/iq80332.h
new file mode 100644
index 0000000..0531656
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/iq80332.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/arch-iop33x/iq80332.h
+ *
+ * Intel IQ80332 evaluation board registers
+ */
+
+#ifndef __IQ80332_H
+#define __IQ80332_H
+
+#define IQ80332_7SEG_1		0xce840000	/* 7-Segment MSB */
+#define IQ80332_7SEG_0		0xce850000	/* 7-Segment LSB (WO) */
+#define IQ80332_ROTARY_SW	0xce8d0000	/* Rotary Switch */
+#define IQ80332_BATT_STAT	0xce8f0000	/* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/irqs.h b/include/asm-arm/arch-iop33x/irqs.h
new file mode 100644
index 0000000..d045f84
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/irqs.h
@@ -0,0 +1,60 @@
+/*
+ * include/asm-arm/arch-iop33x/irqs.h
+ *
+ * Author:	Dave Jiang (dave.jiang@intel.com)
+ * Copyright:	(C) 2003 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __IRQS_H
+#define __IRQS_H
+
+/*
+ * IOP80331 chipset interrupts
+ */
+#define IRQ_IOP33X_DMA0_EOT	0
+#define IRQ_IOP33X_DMA0_EOC	1
+#define IRQ_IOP33X_DMA1_EOT	2
+#define IRQ_IOP33X_DMA1_EOC	3
+#define IRQ_IOP33X_AA_EOT	6
+#define IRQ_IOP33X_AA_EOC	7
+#define IRQ_IOP33X_TIMER0	8
+#define IRQ_IOP33X_TIMER1	9
+#define IRQ_IOP33X_I2C_0	10
+#define IRQ_IOP33X_I2C_1	11
+#define IRQ_IOP33X_MSG		12
+#define IRQ_IOP33X_MSGIBQ	13
+#define IRQ_IOP33X_ATU_BIST	14
+#define IRQ_IOP33X_PERFMON	15
+#define IRQ_IOP33X_CORE_PMU	16
+#define IRQ_IOP33X_XINT0	24
+#define IRQ_IOP33X_XINT1	25
+#define IRQ_IOP33X_XINT2	26
+#define IRQ_IOP33X_XINT3	27
+#define IRQ_IOP33X_XINT8	32
+#define IRQ_IOP33X_XINT9	33
+#define IRQ_IOP33X_XINT10	34
+#define IRQ_IOP33X_XINT11	35
+#define IRQ_IOP33X_XINT12	36
+#define IRQ_IOP33X_XINT13	37
+#define IRQ_IOP33X_XINT14	38
+#define IRQ_IOP33X_XINT15	39
+#define IRQ_IOP33X_UART0	51
+#define IRQ_IOP33X_UART1	52
+#define IRQ_IOP33X_PBIE		53
+#define IRQ_IOP33X_ATU_CRW	54
+#define IRQ_IOP33X_ATU_ERR	55
+#define IRQ_IOP33X_MCU_ERR	56
+#define IRQ_IOP33X_DMA0_ERR	57
+#define IRQ_IOP33X_DMA1_ERR	58
+#define IRQ_IOP33X_AA_ERR	60
+#define IRQ_IOP33X_MSG_ERR	62
+#define IRQ_IOP33X_HPI		63
+
+#define NR_IRQS			64
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/memory.h b/include/asm-arm/arch-iop33x/memory.h
new file mode 100644
index 0000000..0d39139
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/memory.h
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-iop33x/memory.h
+ */
+
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+#include <asm/hardware.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	UL(0x00000000)
+
+/*
+ * Virtual view <-> PCI DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *		address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *		to an address that the kernel can use.
+ */
+#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
+#define __bus_to_virt(x)	(__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/system.h b/include/asm-arm/arch-iop33x/system.h
new file mode 100644
index 0000000..00dd07e
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/system.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-iop33x/system.h
+ *
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	*IOP3XX_PCSR = 0x30;
+
+	/* Jump into ROM at address 0 */
+	cpu_reset(0);
+}
diff --git a/include/asm-arm/arch-iop33x/timex.h b/include/asm-arm/arch-iop33x/timex.h
new file mode 100644
index 0000000..fe3e1e3
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/timex.h
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-iop33x/timex.h
+ *
+ * IOP3xx architecture timex specifications
+ */
+
+#include <asm/hardware.h>
+
+#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/include/asm-arm/arch-iop33x/uncompress.h b/include/asm-arm/arch-iop33x/uncompress.h
new file mode 100644
index 0000000..e17fbc0
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/uncompress.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-arm/arch-iop33x/uncompress.h
+ */
+
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <linux/serial_reg.h>
+#include <asm/hardware.h>
+
+static volatile u32 *uart_base;
+
+#define TX_DONE		(UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void putc(char c)
+{
+	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+		barrier();
+	uart_base[UART_TX] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+	if (machine_is_iq80331() || machine_is_iq80332())
+		uart_base = (volatile u32 *)IOP33X_UART0_PHYS;
+	else
+		uart_base = (volatile u32 *)0xfe800000;
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop33x/vmalloc.h b/include/asm-arm/arch-iop33x/vmalloc.h
new file mode 100644
index 0000000..66f545a
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/vmalloc.h
@@ -0,0 +1,5 @@
+/*
+ * include/asm-arm/arch-iop33x/vmalloc.h
+ */
+
+#define VMALLOC_END	0xfe000000
diff --git a/include/asm-arm/arch-iop3xx/debug-macro.S b/include/asm-arm/arch-iop3xx/debug-macro.S
deleted file mode 100644
index ce007e5..0000000
--- a/include/asm-arm/arch-iop3xx/debug-macro.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/* linux/include/asm-arm/arch-iop3xx/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * 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.
- *
-*/
-
-		.macro	addruart,rx
-		mov	\rx, #0xfe000000	@ physical
-#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
-		orr	\rx, \rx, #0x00800000	@ location of the UART
-#elif defined(CONFIG_ARCH_IOP331)
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x000fe000	@ Physical Base
-		movne	\rx, #0
-		orr	\rx, \rx, #0xfe000000
-		orr	\rx, \rx, #0x00f00000	@ Virtual Base
-		orr	\rx, \rx, #0x00001700   @ location of the UART
-#else
-#error Unknown IOP3XX implementation
-#endif
-		.endm
-
-#if !defined(CONFIG_ARCH_IQ80321) || !defined(CONFIG_ARCH_IQ31244) || !defined(CONFIG_ARCH_IQ80331)
-#define FLOW_CONTROL
-#endif
-#define UART_SHIFT	0
-#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-iop3xx/entry-macro.S b/include/asm-arm/arch-iop3xx/entry-macro.S
deleted file mode 100644
index 926668c..0000000
--- a/include/asm-arm/arch-iop3xx/entry-macro.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * include/asm-arm/arch-iop3xx/entry-macro.S
- *
- * Low-level IRQ helper macros for IOP3xx-based platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <asm/arch/irqs.h>
-
-#if defined(CONFIG_ARCH_IOP321)
-		.macro  disable_fiq
-		.endm
-
-		/*
-		 * Note: only deal with normal interrupts, not FIQ
-		 */
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-		mov     \irqnr, #0
-		mrc     p6, 0, \irqstat, c8, c0, 0      @ Read IINTSRC
-		cmp     \irqstat, #0
-		beq     1001f
-		clz     \irqnr, \irqstat
-		mov     \base, #31
-		subs    \irqnr,\base,\irqnr
-		add     \irqnr,\irqnr,#IRQ_IOP321_DMA0_EOT
-1001:
-		.endm
-
-#elif defined(CONFIG_ARCH_IOP331)
-		.macro  disable_fiq
-		.endm
-
-		/*
-		 * Note: only deal with normal interrupts, not FIQ
-		 */
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-		mov     \irqnr, #0
-		mrc     p6, 0, \irqstat, c4, c0, 0      @ Read IINTSRC0
-		cmp     \irqstat, #0
-		bne     1002f
-		mrc     p6, 0, \irqstat, c5, c0, 0      @ Read IINTSRC1
-		cmp	\irqstat, #0
-		beq	1001f
-		clz	\irqnr, \irqstat
-		rsbs    \irqnr,\irqnr,#31   @ recommend by RMK
-		add	\irqnr,\irqnr,#IRQ_IOP331_XINT8
-		b	1001f
-1002:	clz     \irqnr, \irqstat
-		rsbs    \irqnr,\irqnr,#31   @ recommend by RMK
-		add     \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT
-1001:
-		.endm
-
-#endif
-
diff --git a/include/asm-arm/arch-iop3xx/hardware.h b/include/asm-arm/arch-iop3xx/hardware.h
deleted file mode 100644
index 3b13817..0000000
--- a/include/asm-arm/arch-iop3xx/hardware.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/hardware.h
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/types.h>
-
-/*
- * Note about PCI IO space mappings
- *
- * To make IO space accesses efficient, we store virtual addresses in
- * the IO resources.
- *
- * The PCI IO space is located at virtual 0xfe000000 from physical
- * 0x90000000.  The PCI BARs must be programmed with physical addresses,
- * but when we read them, we convert them to virtual addresses.  See
- * arch/arm/mach-iop3xx/iop3xx-pci.c
- */
-
-#define pcibios_assign_all_busses() 1
-
-
-/*
- * The min PCI I/O and MEM space are dependent on what specific
- * chipset/platform we are running on, so instead of hardcoding with
- * #ifdefs, we just fill these in the platform level PCI init code.
- */
-#ifndef __ASSEMBLY__
-extern unsigned long iop3xx_pcibios_min_io;
-extern unsigned long iop3xx_pcibios_min_mem;
-
-extern unsigned int processor_id;
-#endif
-
-/*
- * We just set these to zero since they are really bogus anyways
- */
-#define PCIBIOS_MIN_IO      (iop3xx_pcibios_min_io)
-#define PCIBIOS_MIN_MEM     (iop3xx_pcibios_min_mem)
-
-/*
- * Generic chipset bits
- *
- */
-#include "iop321.h"
-#include "iop331.h"
-
-/*
- * Board specific bits
- */
-#include "iq80321.h"
-#include "iq31244.h"
-#include "iq80331.h"
-#include "iq80332.h"
-
-#endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-iop3xx/iop321-irqs.h b/include/asm-arm/arch-iop3xx/iop321-irqs.h
deleted file mode 100644
index 2fcc165..0000000
--- a/include/asm-arm/arch-iop3xx/iop321-irqs.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/irqs.h
- *
- * Author:	Rory Bolt <rorybolt@pacbell.net>
- * Copyright:	(C) 2002 Rory Bolt
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#ifndef _IOP321_IRQS_H_
-#define _IOP321_IRQS_H_
-
-/*
- * IOP80321 chipset interrupts
- */
-#define IOP321_IRQ_OFS		0
-#define IOP321_IRQ(x)		(IOP321_IRQ_OFS + (x))
-
-/*
- * On IRQ or FIQ register
- */
-#define IRQ_IOP321_DMA0_EOT	IOP321_IRQ(0)
-#define IRQ_IOP321_DMA0_EOC	IOP321_IRQ(1)
-#define IRQ_IOP321_DMA1_EOT	IOP321_IRQ(2)
-#define IRQ_IOP321_DMA1_EOC	IOP321_IRQ(3)
-#define IRQ_IOP321_RSVD_4	IOP321_IRQ(4)
-#define IRQ_IOP321_RSVD_5	IOP321_IRQ(5)
-#define IRQ_IOP321_AA_EOT	IOP321_IRQ(6)
-#define IRQ_IOP321_AA_EOC	IOP321_IRQ(7)
-#define IRQ_IOP321_CORE_PMON	IOP321_IRQ(8)
-#define IRQ_IOP321_TIMER0	IOP321_IRQ(9)
-#define IRQ_IOP321_TIMER1	IOP321_IRQ(10)
-#define IRQ_IOP321_I2C_0	IOP321_IRQ(11)
-#define IRQ_IOP321_I2C_1	IOP321_IRQ(12)
-#define IRQ_IOP321_MESSAGING	IOP321_IRQ(13)
-#define IRQ_IOP321_ATU_BIST	IOP321_IRQ(14)
-#define IRQ_IOP321_PERFMON	IOP321_IRQ(15)
-#define IRQ_IOP321_CORE_PMU	IOP321_IRQ(16)
-#define IRQ_IOP321_BIU_ERR	IOP321_IRQ(17)
-#define IRQ_IOP321_ATU_ERR	IOP321_IRQ(18)
-#define IRQ_IOP321_MCU_ERR	IOP321_IRQ(19)
-#define IRQ_IOP321_DMA0_ERR	IOP321_IRQ(20)
-#define IRQ_IOP321_DMA1_ERR	IOP321_IRQ(21)
-#define IRQ_IOP321_RSVD_22	IOP321_IRQ(22)
-#define IRQ_IOP321_AA_ERR	IOP321_IRQ(23)
-#define IRQ_IOP321_MSG_ERR	IOP321_IRQ(24)
-#define IRQ_IOP321_SSP		IOP321_IRQ(25)
-#define IRQ_IOP321_RSVD_26	IOP321_IRQ(26)
-#define IRQ_IOP321_XINT0	IOP321_IRQ(27)
-#define IRQ_IOP321_XINT1	IOP321_IRQ(28)
-#define IRQ_IOP321_XINT2	IOP321_IRQ(29)
-#define IRQ_IOP321_XINT3	IOP321_IRQ(30)
-#define IRQ_IOP321_HPI		IOP321_IRQ(31)
-
-#define NR_IOP321_IRQS		(IOP321_IRQ(31) + 1)
-
-#define NR_IRQS			NR_IOP321_IRQS
-
-
-/*
- * Interrupts available on the IQ80321 board
- */
-
-/*
- * On board devices
- */
-#define	IRQ_IQ80321_I82544	IRQ_IOP321_XINT0
-#define IRQ_IQ80321_UART	IRQ_IOP321_XINT1
-
-/*
- * PCI interrupts
- */
-#define	IRQ_IQ80321_INTA	IRQ_IOP321_XINT0
-#define	IRQ_IQ80321_INTB	IRQ_IOP321_XINT1
-#define	IRQ_IQ80321_INTC	IRQ_IOP321_XINT2
-#define	IRQ_IQ80321_INTD	IRQ_IOP321_XINT3
-
-/*
- * Interrupts on the IQ31244 board
- */
-
-/*
- * On board devices
- */
-#define IRQ_IQ31244_UART	IRQ_IOP321_XINT1
-#define	IRQ_IQ31244_I82546	IRQ_IOP321_XINT0
-#define IRQ_IQ31244_SATA	IRQ_IOP321_XINT2
-#define	IRQ_IQ31244_PCIX_SLOT	IRQ_IOP321_XINT3
-
-/*
- * PCI interrupts
- */
-#define	IRQ_IQ31244_INTA	IRQ_IOP321_XINT0
-#define	IRQ_IQ31244_INTB	IRQ_IOP321_XINT1
-#define	IRQ_IQ31244_INTC	IRQ_IOP321_XINT2
-#define	IRQ_IQ31244_INTD	IRQ_IOP321_XINT3
-
-#endif // _IOP321_IRQ_H_
diff --git a/include/asm-arm/arch-iop3xx/iop321.h b/include/asm-arm/arch-iop3xx/iop321.h
deleted file mode 100644
index f8df778..0000000
--- a/include/asm-arm/arch-iop3xx/iop321.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iop321.h
- *
- * Intel IOP321 Chip definitions
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _IOP321_HW_H_
-#define _IOP321_HW_H_
-
-
-/*
- * This is needed for mixed drivers that need to work on all
- * IOP3xx variants but behave slightly differently on each.
- */
-#ifndef __ASSEMBLY__
-#ifdef	CONFIG_ARCH_IOP321
-#define iop_is_321() (((processor_id & 0xfffff5e0) == 0x69052420))
-#else
-#define	iop_is_321()	0
-#endif
-#endif
-
-/*
- * IOP321 I/O and Mem space regions for PCI autoconfiguration
- */
-#define IOP321_PCI_IO_WINDOW_SIZE   0x00010000
-#define IOP321_PCI_LOWER_IO_PA      0x90000000
-#define IOP321_PCI_LOWER_IO_VA      0xfe000000
-#define IOP321_PCI_LOWER_IO_BA      (*IOP321_OIOWTVR)
-#define IOP321_PCI_UPPER_IO_PA      (IOP321_PCI_LOWER_IO_PA + IOP321_PCI_IO_WINDOW_SIZE - 1)
-#define IOP321_PCI_UPPER_IO_VA      (IOP321_PCI_LOWER_IO_VA + IOP321_PCI_IO_WINDOW_SIZE - 1)
-#define IOP321_PCI_UPPER_IO_BA      (IOP321_PCI_LOWER_IO_BA + IOP321_PCI_IO_WINDOW_SIZE - 1)
-#define IOP321_PCI_IO_OFFSET        (IOP321_PCI_LOWER_IO_VA - IOP321_PCI_LOWER_IO_BA)
-
-/* #define IOP321_PCI_MEM_WINDOW_SIZE  (~*IOP321_IALR1 + 1) */
-#define IOP321_PCI_MEM_WINDOW_SIZE  0x04000000 /* 64M outbound window */
-#define IOP321_PCI_LOWER_MEM_PA     0x80000000
-#define IOP321_PCI_LOWER_MEM_BA     (*IOP321_OMWTVR0)
-#define IOP321_PCI_UPPER_MEM_PA     (IOP321_PCI_LOWER_MEM_PA + IOP321_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP321_PCI_UPPER_MEM_BA     (IOP321_PCI_LOWER_MEM_BA + IOP321_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP321_PCI_MEM_OFFSET       (IOP321_PCI_LOWER_MEM_PA - IOP321_PCI_LOWER_MEM_BA)
-
-
-/*
- * IOP321 chipset registers
- */
-#define IOP321_VIRT_MEM_BASE 0xfeffe000  /* chip virtual mem address*/
-#define IOP321_PHYS_MEM_BASE 0xffffe000  /* chip physical memory address */
-#define IOP321_REG_ADDR(reg) (IOP321_VIRT_MEM_BASE | (reg))
-
-/* Reserved 0x00000000 through 0x000000FF */
-
-/* Address Translation Unit 0x00000100 through 0x000001FF */
-#define IOP321_ATUVID     (volatile u16 *)IOP321_REG_ADDR(0x00000100)
-#define IOP321_ATUDID     (volatile u16 *)IOP321_REG_ADDR(0x00000102)
-#define IOP321_ATUCMD     (volatile u16 *)IOP321_REG_ADDR(0x00000104)
-#define IOP321_ATUSR      (volatile u16 *)IOP321_REG_ADDR(0x00000106)
-#define IOP321_ATURID     (volatile u8  *)IOP321_REG_ADDR(0x00000108)
-#define IOP321_ATUCCR     (volatile u32 *)IOP321_REG_ADDR(0x00000109)
-#define IOP321_ATUCLSR    (volatile u8  *)IOP321_REG_ADDR(0x0000010C)
-#define IOP321_ATULT      (volatile u8  *)IOP321_REG_ADDR(0x0000010D)
-#define IOP321_ATUHTR     (volatile u8  *)IOP321_REG_ADDR(0x0000010E)
-#define IOP321_ATUBIST    (volatile u8  *)IOP321_REG_ADDR(0x0000010F)
-#define IOP321_IABAR0     (volatile u32 *)IOP321_REG_ADDR(0x00000110)
-#define IOP321_IAUBAR0    (volatile u32 *)IOP321_REG_ADDR(0x00000114)
-#define IOP321_IABAR1     (volatile u32 *)IOP321_REG_ADDR(0x00000118)
-#define IOP321_IAUBAR1    (volatile u32 *)IOP321_REG_ADDR(0x0000011C)
-#define IOP321_IABAR2     (volatile u32 *)IOP321_REG_ADDR(0x00000120)
-#define IOP321_IAUBAR2    (volatile u32 *)IOP321_REG_ADDR(0x00000124)
-#define IOP321_ASVIR      (volatile u16 *)IOP321_REG_ADDR(0x0000012C)
-#define IOP321_ASIR       (volatile u16 *)IOP321_REG_ADDR(0x0000012E)
-#define IOP321_ERBAR      (volatile u32 *)IOP321_REG_ADDR(0x00000130)
-/* Reserved 0x00000134 through 0x0000013B */
-#define IOP321_ATUILR     (volatile u8  *)IOP321_REG_ADDR(0x0000013C)
-#define IOP321_ATUIPR     (volatile u8  *)IOP321_REG_ADDR(0x0000013D)
-#define IOP321_ATUMGNT    (volatile u8  *)IOP321_REG_ADDR(0x0000013E)
-#define IOP321_ATUMLAT    (volatile u8  *)IOP321_REG_ADDR(0x0000013F)
-#define IOP321_IALR0      (volatile u32 *)IOP321_REG_ADDR(0x00000140)
-#define IOP321_IATVR0     (volatile u32 *)IOP321_REG_ADDR(0x00000144)
-#define IOP321_ERLR       (volatile u32 *)IOP321_REG_ADDR(0x00000148)
-#define IOP321_ERTVR      (volatile u32 *)IOP321_REG_ADDR(0x0000014C)
-#define IOP321_IALR1      (volatile u32 *)IOP321_REG_ADDR(0x00000150)
-#define IOP321_IALR2      (volatile u32 *)IOP321_REG_ADDR(0x00000154)
-#define IOP321_IATVR2     (volatile u32 *)IOP321_REG_ADDR(0x00000158)
-#define IOP321_OIOWTVR    (volatile u32 *)IOP321_REG_ADDR(0x0000015C)
-#define IOP321_OMWTVR0    (volatile u32 *)IOP321_REG_ADDR(0x00000160)
-#define IOP321_OUMWTVR0   (volatile u32 *)IOP321_REG_ADDR(0x00000164)
-#define IOP321_OMWTVR1    (volatile u32 *)IOP321_REG_ADDR(0x00000168)
-#define IOP321_OUMWTVR1   (volatile u32 *)IOP321_REG_ADDR(0x0000016C)
-/* Reserved 0x00000170 through 0x00000177*/
-#define IOP321_OUDWTVR    (volatile u32 *)IOP321_REG_ADDR(0x00000178)
-/* Reserved 0x0000017C through 0x0000017F*/
-#define IOP321_ATUCR      (volatile u32 *)IOP321_REG_ADDR(0x00000180)
-#define IOP321_PCSR       (volatile u32 *)IOP321_REG_ADDR(0x00000184)
-#define IOP321_ATUISR     (volatile u32 *)IOP321_REG_ADDR(0x00000188)
-#define IOP321_ATUIMR     (volatile u32 *)IOP321_REG_ADDR(0x0000018C)
-#define IOP321_IABAR3     (volatile u32 *)IOP321_REG_ADDR(0x00000190)
-#define IOP321_IAUBAR3    (volatile u32 *)IOP321_REG_ADDR(0x00000194)
-#define IOP321_IALR3      (volatile u32 *)IOP321_REG_ADDR(0x00000198)
-#define IOP321_IATVR3     (volatile u32 *)IOP321_REG_ADDR(0x0000019C)
-/* Reserved 0x000001A0 through 0x000001A3*/
-#define IOP321_OCCAR      (volatile u32 *)IOP321_REG_ADDR(0x000001A4)
-/* Reserved 0x000001A8 through 0x000001AB*/
-#define IOP321_OCCDR      (volatile u32 *)IOP321_REG_ADDR(0x000001AC)
-/* Reserved 0x000001B0 through 0x000001BB*/
-#define IOP321_PDSCR      (volatile u32 *)IOP321_REG_ADDR(0x000001BC)
-#define IOP321_PMCAPID    (volatile u8  *)IOP321_REG_ADDR(0x000001C0)
-#define IOP321_PMNEXT     (volatile u8  *)IOP321_REG_ADDR(0x000001C1)
-#define IOP321_APMCR      (volatile u16 *)IOP321_REG_ADDR(0x000001C2)
-#define IOP321_APMCSR     (volatile u16 *)IOP321_REG_ADDR(0x000001C4)
-/* Reserved 0x000001C6 through 0x000001DF */
-#define IOP321_PCIXCAPID  (volatile u8  *)IOP321_REG_ADDR(0x000001E0)
-#define IOP321_PCIXNEXT   (volatile u8  *)IOP321_REG_ADDR(0x000001E1)
-#define IOP321_PCIXCMD    (volatile u16 *)IOP321_REG_ADDR(0x000001E2)
-#define IOP321_PCIXSR     (volatile u32 *)IOP321_REG_ADDR(0x000001E4)
-#define IOP321_PCIIRSR    (volatile u32 *)IOP321_REG_ADDR(0x000001EC)
-
-/* Messaging Unit 0x00000300 through 0x000003FF */
-
-/* Reserved 0x00000300 through 0x0000030c */
-#define IOP321_IMR0       (volatile u32 *)IOP321_REG_ADDR(0x00000310)
-#define IOP321_IMR1       (volatile u32 *)IOP321_REG_ADDR(0x00000314)
-#define IOP321_OMR0       (volatile u32 *)IOP321_REG_ADDR(0x00000318)
-#define IOP321_OMR1       (volatile u32 *)IOP321_REG_ADDR(0x0000031C)
-#define IOP321_IDR        (volatile u32 *)IOP321_REG_ADDR(0x00000320)
-#define IOP321_IISR       (volatile u32 *)IOP321_REG_ADDR(0x00000324)
-#define IOP321_IIMR       (volatile u32 *)IOP321_REG_ADDR(0x00000328)
-#define IOP321_ODR        (volatile u32 *)IOP321_REG_ADDR(0x0000032C)
-#define IOP321_OISR       (volatile u32 *)IOP321_REG_ADDR(0x00000330)
-#define IOP321_OIMR       (volatile u32 *)IOP321_REG_ADDR(0x00000334)
-/* Reserved 0x00000338 through 0x0000034F */
-#define IOP321_MUCR       (volatile u32 *)IOP321_REG_ADDR(0x00000350)
-#define IOP321_QBAR       (volatile u32 *)IOP321_REG_ADDR(0x00000354)
-/* Reserved 0x00000358 through 0x0000035C */
-#define IOP321_IFHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000360)
-#define IOP321_IFTPR      (volatile u32 *)IOP321_REG_ADDR(0x00000364)
-#define IOP321_IPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000368)
-#define IOP321_IPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000036C)
-#define IOP321_OFHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000370)
-#define IOP321_OFTPR      (volatile u32 *)IOP321_REG_ADDR(0x00000374)
-#define IOP321_OPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000378)
-#define IOP321_OPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000037C)
-#define IOP321_IAR        (volatile u32 *)IOP321_REG_ADDR(0x00000380)
-
-#define IOP321_IIxR_MASK	0x7f /* masks all */
-#define IOP321_IIxR_IRI		0x40 /* RC Index Register Interrupt */
-#define IOP321_IIxR_OFQF	0x20 /* RC Output Free Q Full (ERROR) */
-#define IOP321_IIxR_ipq		0x10 /* RC Inbound Post Q (post) */
-#define IOP321_IIxR_ERRDI	0x08 /* RO Error Doorbell Interrupt */
-#define IOP321_IIxR_IDI		0x04 /* RO Inbound Doorbell Interrupt */
-#define IOP321_IIxR_IM1		0x02 /* RC Inbound Message 1 Interrupt */
-#define IOP321_IIxR_IM0		0x01 /* RC Inbound Message 0 Interrupt */
-
-/* Reserved 0x00000384 through 0x000003FF */
-
-/* DMA Controller 0x00000400 through 0x000004FF */
-#define IOP321_DMA0_CCR   (volatile u32 *)IOP321_REG_ADDR(0x00000400)
-#define IOP321_DMA0_CSR   (volatile u32 *)IOP321_REG_ADDR(0x00000404)
-#define IOP321_DMA0_DAR   (volatile u32 *)IOP321_REG_ADDR(0x0000040C)
-#define IOP321_DMA0_NDAR  (volatile u32 *)IOP321_REG_ADDR(0x00000410)
-#define IOP321_DMA0_PADR  (volatile u32 *)IOP321_REG_ADDR(0x00000414)
-#define IOP321_DMA0_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000418)
-#define IOP321_DMA0_LADR  (volatile u32 *)IOP321_REG_ADDR(0X0000041C)
-#define IOP321_DMA0_BCR   (volatile u32 *)IOP321_REG_ADDR(0x00000420)
-#define IOP321_DMA0_DCR   (volatile u32 *)IOP321_REG_ADDR(0x00000424)
-/* Reserved 0x00000428 through 0x0000043C */
-#define IOP321_DMA1_CCR   (volatile u32 *)IOP321_REG_ADDR(0x00000440)
-#define IOP321_DMA1_CSR   (volatile u32 *)IOP321_REG_ADDR(0x00000444)
-#define IOP321_DMA1_DAR   (volatile u32 *)IOP321_REG_ADDR(0x0000044C)
-#define IOP321_DMA1_NDAR  (volatile u32 *)IOP321_REG_ADDR(0x00000450)
-#define IOP321_DMA1_PADR  (volatile u32 *)IOP321_REG_ADDR(0x00000454)
-#define IOP321_DMA1_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000458)
-#define IOP321_DMA1_LADR  (volatile u32 *)IOP321_REG_ADDR(0x0000045C)
-#define IOP321_DMA1_BCR   (volatile u32 *)IOP321_REG_ADDR(0x00000460)
-#define IOP321_DMA1_DCR   (volatile u32 *)IOP321_REG_ADDR(0x00000464)
-/* Reserved 0x00000468 through 0x000004FF */
-
-/* Memory controller 0x00000500 through 0x0005FF */
-
-/* Peripheral bus interface unit 0x00000680 through 0x0006FF */
-#define IOP321_PBCR       (volatile u32 *)IOP321_REG_ADDR(0x00000680)
-#define IOP321_PBISR      (volatile u32 *)IOP321_REG_ADDR(0x00000684)
-#define IOP321_PBBAR0     (volatile u32 *)IOP321_REG_ADDR(0x00000688)
-#define IOP321_PBLR0      (volatile u32 *)IOP321_REG_ADDR(0x0000068C)
-#define IOP321_PBBAR1     (volatile u32 *)IOP321_REG_ADDR(0x00000690)
-#define IOP321_PBLR1      (volatile u32 *)IOP321_REG_ADDR(0x00000694)
-#define IOP321_PBBAR2     (volatile u32 *)IOP321_REG_ADDR(0x00000698)
-#define IOP321_PBLR2      (volatile u32 *)IOP321_REG_ADDR(0x0000069C)
-#define IOP321_PBBAR3     (volatile u32 *)IOP321_REG_ADDR(0x000006A0)
-#define IOP321_PBLR3      (volatile u32 *)IOP321_REG_ADDR(0x000006A4)
-#define IOP321_PBBAR4     (volatile u32 *)IOP321_REG_ADDR(0x000006A8)
-#define IOP321_PBLR4      (volatile u32 *)IOP321_REG_ADDR(0x000006AC)
-#define IOP321_PBBAR5     (volatile u32 *)IOP321_REG_ADDR(0x000006B0)
-#define IOP321_PBLR5      (volatile u32 *)IOP321_REG_ADDR(0x000006B4)
-#define IOP321_PBDSCR     (volatile u32 *)IOP321_REG_ADDR(0x000006B8)
-/* Reserved 0x000006BC */
-#define IOP321_PMBR0      (volatile u32 *)IOP321_REG_ADDR(0x000006C0)
-/* Reserved 0x000006C4 through 0x000006DC */
-#define IOP321_PMBR1      (volatile u32 *)IOP321_REG_ADDR(0x000006E0)
-#define IOP321_PMBR2      (volatile u32 *)IOP321_REG_ADDR(0x000006E4)
-
-#define IOP321_PBCR_EN    0x1
-
-#define IOP321_PBISR_BOOR_ERR 0x1
-
-/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
-#define IOP321_GTMR	(volatile u32 *)IOP321_REG_ADDR(0x00000700)
-#define IOP321_ESR	(volatile u32 *)IOP321_REG_ADDR(0x00000704)
-#define IOP321_EMISR	(volatile u32 *)IOP321_REG_ADDR(0x00000708)
-/* reserved 0x00000070c */
-#define IOP321_GTSR	(volatile u32 *)IOP321_REG_ADDR(0x00000710)
-/* PERC0 DOESN'T EXIST - index from 1! */
-#define IOP321_PERCR0	(volatile u32 *)IOP321_REG_ADDR(0x00000710)
-
-#define IOP321_GTMR_NGCE	0x04 /* (Not) Global Counter Enable */
-
-/* Internal arbitration unit 0x00000780 through 0x0007BF */
-#define IOP321_IACR	(volatile u32 *)IOP321_REG_ADDR(0x00000780)
-#define IOP321_MTTR1	(volatile u32 *)IOP321_REG_ADDR(0x00000784)
-#define IOP321_MTTR2	(volatile u32 *)IOP321_REG_ADDR(0x00000788)
-
-/* General Purpose I/O Registers */
-#define IOP321_GPOE       (volatile u32 *)IOP321_REG_ADDR(0x000007C4)
-#define IOP321_GPID       (volatile u32 *)IOP321_REG_ADDR(0x000007C8)
-#define IOP321_GPOD       (volatile u32 *)IOP321_REG_ADDR(0x000007CC)
-
-/* Interrupt Controller */
-#define IOP321_INTCTL     (volatile u32 *)IOP321_REG_ADDR(0x000007D0)
-#define IOP321_INTSTR     (volatile u32 *)IOP321_REG_ADDR(0x000007D4)
-#define IOP321_IINTSRC    (volatile u32 *)IOP321_REG_ADDR(0x000007D8)
-#define IOP321_FINTSRC    (volatile u32 *)IOP321_REG_ADDR(0x000007DC)
-
-/* Timers */
-
-#define IOP321_TU_TMR0		(volatile u32 *)IOP321_REG_ADDR(0x000007E0)
-#define IOP321_TU_TMR1		(volatile u32 *)IOP321_REG_ADDR(0x000007E4)
-
-#ifdef CONFIG_ARCH_IQ80321
-#define	IOP321_TICK_RATE	200000000	/* 200 MHz clock */
-#elif defined(CONFIG_ARCH_IQ31244)
-#define IOP321_TICK_RATE	198000000	/* 33.000 MHz crystal */
-#endif
-
-#ifdef CONFIG_ARCH_EP80219
-#undef IOP321_TICK_RATE
-#define IOP321_TICK_RATE 200000000 /* 33.333333 Mhz crystal */
-#endif
-
-#define IOP321_TMR_TC		0x01
-#define	IOP321_TMR_EN		0x02
-#define IOP321_TMR_RELOAD	0x04
-#define	IOP321_TMR_PRIVILEGED	0x09
-
-#define	IOP321_TMR_RATIO_1_1	0x00
-#define	IOP321_TMR_RATIO_4_1	0x10
-#define	IOP321_TMR_RATIO_8_1	0x20
-#define	IOP321_TMR_RATIO_16_1	0x30
-
-#define IOP321_TU_TCR0    (volatile u32 *)IOP321_REG_ADDR(0x000007E8)
-#define IOP321_TU_TCR1    (volatile u32 *)IOP321_REG_ADDR(0x000007EC)
-#define IOP321_TU_TRR0    (volatile u32 *)IOP321_REG_ADDR(0x000007F0)
-#define IOP321_TU_TRR1    (volatile u32 *)IOP321_REG_ADDR(0x000007F4)
-#define IOP321_TU_TISR    (volatile u32 *)IOP321_REG_ADDR(0x000007F8)
-#define IOP321_TU_WDTCR   (volatile u32 *)IOP321_REG_ADDR(0x000007FC)
-
-/* Application accelerator unit 0x00000800 - 0x000008FF */
-#define IOP321_AAU_ACR     (volatile u32 *)IOP321_REG_ADDR(0x00000800)
-#define IOP321_AAU_ASR     (volatile u32 *)IOP321_REG_ADDR(0x00000804)
-#define IOP321_AAU_ADAR    (volatile u32 *)IOP321_REG_ADDR(0x00000808)
-#define IOP321_AAU_ANDAR   (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
-#define IOP321_AAU_SAR1    (volatile u32 *)IOP321_REG_ADDR(0x00000810)
-#define IOP321_AAU_SAR2    (volatile u32 *)IOP321_REG_ADDR(0x00000814)
-#define IOP321_AAU_SAR3    (volatile u32 *)IOP321_REG_ADDR(0x00000818)
-#define IOP321_AAU_SAR4    (volatile u32 *)IOP321_REG_ADDR(0x0000081C)
-#define IOP321_AAU_SAR5    (volatile u32 *)IOP321_REG_ADDR(0x0000082C)
-#define IOP321_AAU_SAR6    (volatile u32 *)IOP321_REG_ADDR(0x00000830)
-#define IOP321_AAU_SAR7    (volatile u32 *)IOP321_REG_ADDR(0x00000834)
-#define IOP321_AAU_SAR8    (volatile u32 *)IOP321_REG_ADDR(0x00000838)
-#define IOP321_AAU_SAR9    (volatile u32 *)IOP321_REG_ADDR(0x00000840)
-#define IOP321_AAU_SAR10   (volatile u32 *)IOP321_REG_ADDR(0x00000844)
-#define IOP321_AAU_SAR11   (volatile u32 *)IOP321_REG_ADDR(0x00000848)
-#define IOP321_AAU_SAR12   (volatile u32 *)IOP321_REG_ADDR(0x0000084C)
-#define IOP321_AAU_SAR13   (volatile u32 *)IOP321_REG_ADDR(0x00000850)
-#define IOP321_AAU_SAR14   (volatile u32 *)IOP321_REG_ADDR(0x00000854)
-#define IOP321_AAU_SAR15   (volatile u32 *)IOP321_REG_ADDR(0x00000858)
-#define IOP321_AAU_SAR16   (volatile u32 *)IOP321_REG_ADDR(0x0000085C)
-#define IOP321_AAU_SAR17   (volatile u32 *)IOP321_REG_ADDR(0x00000864)
-#define IOP321_AAU_SAR18   (volatile u32 *)IOP321_REG_ADDR(0x00000868)
-#define IOP321_AAU_SAR19   (volatile u32 *)IOP321_REG_ADDR(0x0000086C)
-#define IOP321_AAU_SAR20   (volatile u32 *)IOP321_REG_ADDR(0x00000870)
-#define IOP321_AAU_SAR21   (volatile u32 *)IOP321_REG_ADDR(0x00000874)
-#define IOP321_AAU_SAR22   (volatile u32 *)IOP321_REG_ADDR(0x00000878)
-#define IOP321_AAU_SAR23   (volatile u32 *)IOP321_REG_ADDR(0x0000087C)
-#define IOP321_AAU_SAR24   (volatile u32 *)IOP321_REG_ADDR(0x00000880)
-#define IOP321_AAU_SAR25   (volatile u32 *)IOP321_REG_ADDR(0x00000888)
-#define IOP321_AAU_SAR26   (volatile u32 *)IOP321_REG_ADDR(0x0000088C)
-#define IOP321_AAU_SAR27   (volatile u32 *)IOP321_REG_ADDR(0x00000890)
-#define IOP321_AAU_SAR28   (volatile u32 *)IOP321_REG_ADDR(0x00000894)
-#define IOP321_AAU_SAR29   (volatile u32 *)IOP321_REG_ADDR(0x00000898)
-#define IOP321_AAU_SAR30   (volatile u32 *)IOP321_REG_ADDR(0x0000089C)
-#define IOP321_AAU_SAR31   (volatile u32 *)IOP321_REG_ADDR(0x000008A0)
-#define IOP321_AAU_SAR32   (volatile u32 *)IOP321_REG_ADDR(0x000008A4)
-#define IOP321_AAU_DAR     (volatile u32 *)IOP321_REG_ADDR(0x00000820)
-#define IOP321_AAU_ABCR    (volatile u32 *)IOP321_REG_ADDR(0x00000824)
-#define IOP321_AAU_ADCR    (volatile u32 *)IOP321_REG_ADDR(0x00000828)
-#define IOP321_AAU_EDCR0   (volatile u32 *)IOP321_REG_ADDR(0x0000083c)
-#define IOP321_AAU_EDCR1   (volatile u32 *)IOP321_REG_ADDR(0x00000860)
-#define IOP321_AAU_EDCR2   (volatile u32 *)IOP321_REG_ADDR(0x00000884)
-
-
-/* SSP serial port unit 0x00001600 - 0x0000167F */
-/* I2C bus interface unit 0x00001680 - 0x000016FF */
-#define IOP321_ICR0       (volatile u32 *)IOP321_REG_ADDR(0x00001680)
-#define IOP321_ISR0       (volatile u32 *)IOP321_REG_ADDR(0x00001684)
-#define IOP321_ISAR0      (volatile u32 *)IOP321_REG_ADDR(0x00001688)
-#define IOP321_IDBR0      (volatile u32 *)IOP321_REG_ADDR(0x0000168C)
-/* Reserved 0x00001690 */
-#define IOP321_IBMR0      (volatile u32 *)IOP321_REG_ADDR(0x00001694)
-/* Reserved 0x00001698 */
-/* Reserved 0x0000169C */
-#define IOP321_ICR1       (volatile u32 *)IOP321_REG_ADDR(0x000016A0)
-#define IOP321_ISR1       (volatile u32 *)IOP321_REG_ADDR(0x000016A4)
-#define IOP321_ISAR1      (volatile u32 *)IOP321_REG_ADDR(0x000016A8)
-#define IOP321_IDBR1      (volatile u32 *)IOP321_REG_ADDR(0x000016AC)
-#define IOP321_IBMR1      (volatile u32 *)IOP321_REG_ADDR(0x000016B4)
-/* Reserved 0x000016B8 through 0x000016FC */
-
-/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
-
-
-#ifndef __ASSEMBLY__
-extern void iop321_map_io(void);
-extern void iop321_init_irq(void);
-extern void iop321_time_init(void);
-#endif
-
-#endif // _IOP321_HW_H_
diff --git a/include/asm-arm/arch-iop3xx/iop331-irqs.h b/include/asm-arm/arch-iop3xx/iop331-irqs.h
deleted file mode 100644
index 7135ad7..0000000
--- a/include/asm-arm/arch-iop3xx/iop331-irqs.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/irqs.h
- *
- * Author:	Dave Jiang (dave.jiang@intel.com)
- * Copyright:	(C) 2003 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#ifndef _IOP331_IRQS_H_
-#define _IOP331_IRQS_H_
-
-/*
- * IOP80331 chipset interrupts
- */
-#define IOP331_IRQ_OFS		0
-#define IOP331_IRQ(x)		(IOP331_IRQ_OFS + (x))
-
-/*
- * On IRQ or FIQ register
- */
-#define IRQ_IOP331_DMA0_EOT	IOP331_IRQ(0)
-#define IRQ_IOP331_DMA0_EOC	IOP331_IRQ(1)
-#define IRQ_IOP331_DMA1_EOT	IOP331_IRQ(2)
-#define IRQ_IOP331_DMA1_EOC	IOP331_IRQ(3)
-#define IRQ_IOP331_RSVD_4	IOP331_IRQ(4)
-#define IRQ_IOP331_RSVD_5	IOP331_IRQ(5)
-#define IRQ_IOP331_AA_EOT	IOP331_IRQ(6)
-#define IRQ_IOP331_AA_EOC	IOP331_IRQ(7)
-#define IRQ_IOP331_TIMER0	IOP331_IRQ(8)
-#define IRQ_IOP331_TIMER1	IOP331_IRQ(9)
-#define IRQ_IOP331_I2C_0	IOP331_IRQ(10)
-#define IRQ_IOP331_I2C_1	IOP331_IRQ(11)
-#define IRQ_IOP331_MSG	    IOP331_IRQ(12)
-#define IRQ_IOP331_MSGIBQ   IOP331_IRQ(13)
-#define IRQ_IOP331_ATU_BIST	IOP331_IRQ(14)
-#define IRQ_IOP331_PERFMON	IOP331_IRQ(15)
-#define IRQ_IOP331_CORE_PMU	IOP331_IRQ(16)
-#define IRQ_IOP331_RSVD_17	IOP331_IRQ(17)
-#define IRQ_IOP331_RSVD_18	IOP331_IRQ(18)
-#define IRQ_IOP331_RSVD_19	IOP331_IRQ(19)
-#define IRQ_IOP331_RSVD_20	IOP331_IRQ(20)
-#define IRQ_IOP331_RSVD_21	IOP331_IRQ(21)
-#define IRQ_IOP331_RSVD_22	IOP331_IRQ(22)
-#define IRQ_IOP331_RSVD_23	IOP331_IRQ(23)
-#define IRQ_IOP331_XINT0	IOP331_IRQ(24)
-#define IRQ_IOP331_XINT1	IOP331_IRQ(25)
-#define IRQ_IOP331_XINT2	IOP331_IRQ(26)
-#define IRQ_IOP331_XINT3	IOP331_IRQ(27)
-#define IRQ_IOP331_RSVD_28  IOP331_IRQ(28)
-#define IRQ_IOP331_RSVD_29  IOP331_IRQ(29)
-#define IRQ_IOP331_RSVD_30  IOP331_IRQ(30)
-#define IRQ_IOP331_RSVD_31  IOP331_IRQ(31)
-#define IRQ_IOP331_XINT8    IOP331_IRQ(32)  // 0
-#define IRQ_IOP331_XINT9    IOP331_IRQ(33)  // 1
-#define IRQ_IOP331_XINT10   IOP331_IRQ(34)  // 2
-#define IRQ_IOP331_XINT11   IOP331_IRQ(35)  // 3
-#define IRQ_IOP331_XINT12   IOP331_IRQ(36)  // 4
-#define IRQ_IOP331_XINT13   IOP331_IRQ(37)  // 5
-#define IRQ_IOP331_XINT14   IOP331_IRQ(38)  // 6
-#define IRQ_IOP331_XINT15   IOP331_IRQ(39)  // 7
-#define IRQ_IOP331_RSVD_40  IOP331_IRQ(40)  // 8
-#define IRQ_IOP331_RSVD_41  IOP331_IRQ(41)  // 9
-#define IRQ_IOP331_RSVD_42  IOP331_IRQ(42)  // 10
-#define IRQ_IOP331_RSVD_43  IOP331_IRQ(43)  // 11
-#define IRQ_IOP331_RSVD_44  IOP331_IRQ(44)  // 12
-#define IRQ_IOP331_RSVD_45  IOP331_IRQ(45)  // 13
-#define IRQ_IOP331_RSVD_46  IOP331_IRQ(46)  // 14
-#define IRQ_IOP331_RSVD_47  IOP331_IRQ(47)  // 15
-#define IRQ_IOP331_RSVD_48  IOP331_IRQ(48)  // 16
-#define IRQ_IOP331_RSVD_49  IOP331_IRQ(49)  // 17
-#define IRQ_IOP331_RSVD_50  IOP331_IRQ(50)  // 18
-#define IRQ_IOP331_UART0    IOP331_IRQ(51)  // 19
-#define IRQ_IOP331_UART1    IOP331_IRQ(52)  // 20
-#define IRQ_IOP331_PBIE     IOP331_IRQ(53)  // 21
-#define IRQ_IOP331_ATU_CRW  IOP331_IRQ(54)  // 22
-#define IRQ_IOP331_ATU_ERR	IOP331_IRQ(55)  // 23
-#define IRQ_IOP331_MCU_ERR	IOP331_IRQ(56)  // 24
-#define IRQ_IOP331_DMA0_ERR	IOP331_IRQ(57)  // 25
-#define IRQ_IOP331_DMA1_ERR	IOP331_IRQ(58)  // 26
-#define IRQ_IOP331_RSVD_59  IOP331_IRQ(59)  // 27
-#define IRQ_IOP331_AA_ERR	IOP331_IRQ(60)  // 28
-#define IRQ_IOP331_RSVD_61  IOP331_IRQ(61)  // 29
-#define IRQ_IOP331_MSG_ERR	IOP331_IRQ(62)  // 30
-#define IRQ_IOP331_HPI		IOP331_IRQ(63)  // 31
-
-#define NR_IOP331_IRQS		(IOP331_IRQ(63) + 1)
-
-#define NR_IRQS			NR_IOP331_IRQS
-
-
-/*
- * Interrupts available on the IQ80331 board
- */
-
-/*
- * On board devices
- */
-#define	IRQ_IQ80331_I82544	IRQ_IOP331_XINT0
-#define IRQ_IQ80331_UART0	IRQ_IOP331_UART0
-#define IRQ_IQ80331_UART1	IRQ_IOP331_UART1
-
-/*
- * PCI interrupts
- */
-#define	IRQ_IQ80331_INTA	IRQ_IOP331_XINT0
-#define	IRQ_IQ80331_INTB	IRQ_IOP331_XINT1
-#define	IRQ_IQ80331_INTC	IRQ_IOP331_XINT2
-#define	IRQ_IQ80331_INTD	IRQ_IOP331_XINT3
-
-/*
- * Interrupts available on the IQ80332 board
- */
-
-/*
- * On board devices
- */
-#define	IRQ_IQ80332_I82544	IRQ_IOP331_XINT0
-#define IRQ_IQ80332_UART0	IRQ_IOP331_UART0
-#define IRQ_IQ80332_UART1	IRQ_IOP331_UART1
-
-/*
- * PCI interrupts
- */
-#define	IRQ_IQ80332_INTA	IRQ_IOP331_XINT0
-#define	IRQ_IQ80332_INTB	IRQ_IOP331_XINT1
-#define	IRQ_IQ80332_INTC	IRQ_IOP331_XINT2
-#define	IRQ_IQ80332_INTD	IRQ_IOP331_XINT3
-
-#endif // _IOP331_IRQ_H_
diff --git a/include/asm-arm/arch-iop3xx/iop331.h b/include/asm-arm/arch-iop3xx/iop331.h
deleted file mode 100644
index fbf0cc1..0000000
--- a/include/asm-arm/arch-iop3xx/iop331.h
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iop331.h
- *
- * Intel IOP331 Chip definitions
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2003, 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _IOP331_HW_H_
-#define _IOP331_HW_H_
-
-
-/*
- * This is needed for mixed drivers that need to work on all
- * IOP3xx variants but behave slightly differently on each.
- */
-#ifndef __ASSEMBLY__
-#ifdef	CONFIG_ARCH_IOP331
-/*#define	iop_is_331()	((processor_id & 0xffffffb0) == 0x69054090) */
-#define	iop_is_331()	((processor_id & 0xffffff30) == 0x69054010)
-#else
-#define	iop_is_331()	0
-#endif
-#endif
-
-/*
- * IOP331 I/O and Mem space regions for PCI autoconfiguration
- */
-#define IOP331_PCI_IO_WINDOW_SIZE   0x00010000
-#define IOP331_PCI_LOWER_IO_PA      0x90000000
-#define IOP331_PCI_LOWER_IO_VA      0xfe000000
-#define IOP331_PCI_LOWER_IO_BA      (*IOP331_OIOWTVR)
-#define IOP331_PCI_UPPER_IO_PA      (IOP331_PCI_LOWER_IO_PA + IOP331_PCI_IO_WINDOW_SIZE - 1)
-#define IOP331_PCI_UPPER_IO_VA      (IOP331_PCI_LOWER_IO_VA + IOP331_PCI_IO_WINDOW_SIZE - 1)
-#define IOP331_PCI_UPPER_IO_BA      (IOP331_PCI_LOWER_IO_BA + IOP331_PCI_IO_WINDOW_SIZE - 1)
-#define IOP331_PCI_IO_OFFSET        (IOP331_PCI_LOWER_IO_VA - IOP331_PCI_LOWER_IO_BA)
-
-/* this can be 128M if OMWTVR1 is set */
-#define IOP331_PCI_MEM_WINDOW_SIZE	0x04000000 /* 64M outbound window */
-/* #define IOP331_PCI_MEM_WINDOW_SIZE  (~*IOP331_IALR1 + 1) */
-#define IOP331_PCI_LOWER_MEM_PA     0x80000000
-#define IOP331_PCI_LOWER_MEM_BA     (*IOP331_OMWTVR0)
-#define IOP331_PCI_UPPER_MEM_PA     (IOP331_PCI_LOWER_MEM_PA + IOP331_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP331_PCI_UPPER_MEM_BA     (IOP331_PCI_LOWER_MEM_BA + IOP331_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP331_PCI_MEM_OFFSET       (IOP331_PCI_LOWER_MEM_PA - IOP331_PCI_LOWER_MEM_BA)
-
-/*
- * IOP331 chipset registers
- */
-#define IOP331_VIRT_MEM_BASE  0xfeffe000  /* chip virtual mem address*/
-#define IOP331_PHYS_MEM_BASE  0xffffe000  /* chip physical memory address */
-#define IOP331_REG_ADDR(reg) (IOP331_VIRT_MEM_BASE | (reg))
-
-/* Reserved 0x00000000 through 0x000000FF */
-
-/* Address Translation Unit 0x00000100 through 0x000001FF */
-#define IOP331_ATUVID     (volatile u16 *)IOP331_REG_ADDR(0x00000100)
-#define IOP331_ATUDID     (volatile u16 *)IOP331_REG_ADDR(0x00000102)
-#define IOP331_ATUCMD     (volatile u16 *)IOP331_REG_ADDR(0x00000104)
-#define IOP331_ATUSR      (volatile u16 *)IOP331_REG_ADDR(0x00000106)
-#define IOP331_ATURID     (volatile u8  *)IOP331_REG_ADDR(0x00000108)
-#define IOP331_ATUCCR     (volatile u32 *)IOP331_REG_ADDR(0x00000109)
-#define IOP331_ATUCLSR    (volatile u8  *)IOP331_REG_ADDR(0x0000010C)
-#define IOP331_ATULT      (volatile u8  *)IOP331_REG_ADDR(0x0000010D)
-#define IOP331_ATUHTR     (volatile u8  *)IOP331_REG_ADDR(0x0000010E)
-#define IOP331_ATUBIST    (volatile u8  *)IOP331_REG_ADDR(0x0000010F)
-#define IOP331_IABAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000110)
-#define IOP331_IAUBAR0    (volatile u32 *)IOP331_REG_ADDR(0x00000114)
-#define IOP331_IABAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000118)
-#define IOP331_IAUBAR1    (volatile u32 *)IOP331_REG_ADDR(0x0000011C)
-#define IOP331_IABAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000120)
-#define IOP331_IAUBAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000124)
-#define IOP331_ASVIR      (volatile u16 *)IOP331_REG_ADDR(0x0000012C)
-#define IOP331_ASIR       (volatile u16 *)IOP331_REG_ADDR(0x0000012E)
-#define IOP331_ERBAR      (volatile u32 *)IOP331_REG_ADDR(0x00000130)
-#define IOP331_ATU_CAPPTR (volatile u32 *)IOP331_REG_ADDR(0x00000134)
-/* Reserved 0x00000138 through 0x0000013B */
-#define IOP331_ATUILR     (volatile u8  *)IOP331_REG_ADDR(0x0000013C)
-#define IOP331_ATUIPR     (volatile u8  *)IOP331_REG_ADDR(0x0000013D)
-#define IOP331_ATUMGNT    (volatile u8  *)IOP331_REG_ADDR(0x0000013E)
-#define IOP331_ATUMLAT    (volatile u8  *)IOP331_REG_ADDR(0x0000013F)
-#define IOP331_IALR0      (volatile u32 *)IOP331_REG_ADDR(0x00000140)
-#define IOP331_IATVR0     (volatile u32 *)IOP331_REG_ADDR(0x00000144)
-#define IOP331_ERLR       (volatile u32 *)IOP331_REG_ADDR(0x00000148)
-#define IOP331_ERTVR      (volatile u32 *)IOP331_REG_ADDR(0x0000014C)
-#define IOP331_IALR1      (volatile u32 *)IOP331_REG_ADDR(0x00000150)
-#define IOP331_IALR2      (volatile u32 *)IOP331_REG_ADDR(0x00000154)
-#define IOP331_IATVR2     (volatile u32 *)IOP331_REG_ADDR(0x00000158)
-#define IOP331_OIOWTVR    (volatile u32 *)IOP331_REG_ADDR(0x0000015C)
-#define IOP331_OMWTVR0    (volatile u32 *)IOP331_REG_ADDR(0x00000160)
-#define IOP331_OUMWTVR0   (volatile u32 *)IOP331_REG_ADDR(0x00000164)
-#define IOP331_OMWTVR1    (volatile u32 *)IOP331_REG_ADDR(0x00000168)
-#define IOP331_OUMWTVR1   (volatile u32 *)IOP331_REG_ADDR(0x0000016C)
-/* Reserved 0x00000170 through 0x00000177*/
-#define IOP331_OUDWTVR    (volatile u32 *)IOP331_REG_ADDR(0x00000178)
-/* Reserved 0x0000017C through 0x0000017F*/
-#define IOP331_ATUCR      (volatile u32 *)IOP331_REG_ADDR(0x00000180)
-#define IOP331_PCSR       (volatile u32 *)IOP331_REG_ADDR(0x00000184)
-#define IOP331_ATUISR     (volatile u32 *)IOP331_REG_ADDR(0x00000188)
-#define IOP331_ATUIMR     (volatile u32 *)IOP331_REG_ADDR(0x0000018C)
-#define IOP331_IABAR3     (volatile u32 *)IOP331_REG_ADDR(0x00000190)
-#define IOP331_IAUBAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000194)
-#define IOP331_IALR3      (volatile u32 *)IOP331_REG_ADDR(0x00000198)
-#define IOP331_IATVR3     (volatile u32 *)IOP331_REG_ADDR(0x0000019C)
-/* Reserved 0x000001A0 through 0x000001A3*/
-#define IOP331_OCCAR      (volatile u32 *)IOP331_REG_ADDR(0x000001A4)
-/* Reserved 0x000001A8 through 0x000001AB*/
-#define IOP331_OCCDR      (volatile u32 *)IOP331_REG_ADDR(0x000001AC)
-/* Reserved 0x000001B0 through 0x000001BB*/
-#define IOP331_VPDCAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001B8)
-#define IOP331_VPDNXTP    (volatile u8 *)IOP331_REG_ADDR(0x000001B9)
-#define IOP331_VPDAR	  (volatile u16 *)IOP331_REG_ADDR(0x000001BA)
-#define IOP331_VPDDR      (volatile u32 *)IOP331_REG_ADDR(0x000001BC)
-#define IOP331_PMCAPID    (volatile u8 *)IOP331_REG_ADDR(0x000001C0)
-#define IOP331_PMNEXT     (volatile u8 *)IOP331_REG_ADDR(0x000001C1)
-#define IOP331_APMCR      (volatile u16 *)IOP331_REG_ADDR(0x000001C2)
-#define IOP331_APMCSR     (volatile u16 *)IOP331_REG_ADDR(0x000001C4)
-/* Reserved 0x000001C6 through 0x000001CF */
-#define IOP331_MSICAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001D0)
-#define IOP331_MSINXTP	  (volatile u8 *)IOP331_REG_ADDR(0x000001D1)
-#define IOP331_MSIMCR     (volatile u16 *)IOP331_REG_ADDR(0x000001D2)
-#define IOP331_MSIMAR     (volatile u32 *)IOP331_REG_ADDR(0x000001D4)
-#define IOP331_MSIMUAR	  (volatile u32 *)IOP331_REG_ADDR(0x000001D8)
-#define IOP331_MSIMDR	  (volatile u32 *)IOP331_REG_ADDR(0x000001DC)
-#define IOP331_PCIXCAPID  (volatile u8 *)IOP331_REG_ADDR(0x000001E0)
-#define IOP331_PCIXNEXT   (volatile u8 *)IOP331_REG_ADDR(0x000001E1)
-#define IOP331_PCIXCMD    (volatile u16 *)IOP331_REG_ADDR(0x000001E2)
-#define IOP331_PCIXSR     (volatile u32 *)IOP331_REG_ADDR(0x000001E4)
-#define IOP331_PCIIRSR    (volatile u32 *)IOP331_REG_ADDR(0x000001EC)
-
-/* Messaging Unit 0x00000300 through 0x000003FF */
-
-/* Reserved 0x00000300 through 0x0000030c */
-#define IOP331_IMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000310)
-#define IOP331_IMR1       (volatile u32 *)IOP331_REG_ADDR(0x00000314)
-#define IOP331_OMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000318)
-#define IOP331_OMR1       (volatile u32 *)IOP331_REG_ADDR(0x0000031C)
-#define IOP331_IDR        (volatile u32 *)IOP331_REG_ADDR(0x00000320)
-#define IOP331_IISR       (volatile u32 *)IOP331_REG_ADDR(0x00000324)
-#define IOP331_IIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000328)
-#define IOP331_ODR        (volatile u32 *)IOP331_REG_ADDR(0x0000032C)
-#define IOP331_OISR       (volatile u32 *)IOP331_REG_ADDR(0x00000330)
-#define IOP331_OIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000334)
-/* Reserved 0x00000338 through 0x0000034F */
-#define IOP331_MUCR       (volatile u32 *)IOP331_REG_ADDR(0x00000350)
-#define IOP331_QBAR       (volatile u32 *)IOP331_REG_ADDR(0x00000354)
-/* Reserved 0x00000358 through 0x0000035C */
-#define IOP331_IFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000360)
-#define IOP331_IFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000364)
-#define IOP331_IPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000368)
-#define IOP331_IPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000036C)
-#define IOP331_OFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000370)
-#define IOP331_OFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000374)
-#define IOP331_OPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000378)
-#define IOP331_OPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000037C)
-#define IOP331_IAR        (volatile u32 *)IOP331_REG_ADDR(0x00000380)
-/* Reserved 0x00000384 through 0x000003FF */
-
-/* DMA Controller 0x00000400 through 0x000004FF */
-#define IOP331_DMA0_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000400)
-#define IOP331_DMA0_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000404)
-#define IOP331_DMA0_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000040C)
-#define IOP331_DMA0_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000410)
-#define IOP331_DMA0_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000414)
-#define IOP331_DMA0_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000418)
-#define IOP331_DMA0_LADR  (volatile u32 *)IOP331_REG_ADDR(0X0000041C)
-#define IOP331_DMA0_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000420)
-#define IOP331_DMA0_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000424)
-/* Reserved 0x00000428 through 0x0000043C */
-#define IOP331_DMA1_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000440)
-#define IOP331_DMA1_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000444)
-#define IOP331_DMA1_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000044C)
-#define IOP331_DMA1_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000450)
-#define IOP331_DMA1_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000454)
-#define IOP331_DMA1_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000458)
-#define IOP331_DMA1_LADR  (volatile u32 *)IOP331_REG_ADDR(0x0000045C)
-#define IOP331_DMA1_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000460)
-#define IOP331_DMA1_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000464)
-/* Reserved 0x00000468 through 0x000004FF */
-
-/* Memory controller 0x00000500 through 0x0005FF */
-
-/* Peripheral bus interface unit 0x00000680 through 0x0006FF */
-#define IOP331_PBCR       (volatile u32 *)IOP331_REG_ADDR(0x00000680)
-#define IOP331_PBISR      (volatile u32 *)IOP331_REG_ADDR(0x00000684)
-#define IOP331_PBBAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000688)
-#define IOP331_PBLR0      (volatile u32 *)IOP331_REG_ADDR(0x0000068C)
-#define IOP331_PBBAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000690)
-#define IOP331_PBLR1      (volatile u32 *)IOP331_REG_ADDR(0x00000694)
-#define IOP331_PBBAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000698)
-#define IOP331_PBLR2      (volatile u32 *)IOP331_REG_ADDR(0x0000069C)
-#define IOP331_PBBAR3     (volatile u32 *)IOP331_REG_ADDR(0x000006A0)
-#define IOP331_PBLR3      (volatile u32 *)IOP331_REG_ADDR(0x000006A4)
-#define IOP331_PBBAR4     (volatile u32 *)IOP331_REG_ADDR(0x000006A8)
-#define IOP331_PBLR4      (volatile u32 *)IOP331_REG_ADDR(0x000006AC)
-#define IOP331_PBBAR5     (volatile u32 *)IOP331_REG_ADDR(0x000006B0)
-#define IOP331_PBLR5      (volatile u32 *)IOP331_REG_ADDR(0x000006B4)
-#define IOP331_PBDSCR     (volatile u32 *)IOP331_REG_ADDR(0x000006B8)
-/* Reserved 0x000006BC */
-#define IOP331_PMBR0      (volatile u32 *)IOP331_REG_ADDR(0x000006C0)
-/* Reserved 0x000006C4 through 0x000006DC */
-#define IOP331_PMBR1      (volatile u32 *)IOP331_REG_ADDR(0x000006E0)
-#define IOP331_PMBR2      (volatile u32 *)IOP331_REG_ADDR(0x000006E4)
-
-#define IOP331_PBCR_EN    0x1
-
-#define IOP331_PBISR_BOOR_ERR 0x1
-
-
-
-/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
-/* Internal arbitration unit 0x00000780 through 0x0007BF */
-
-/* Interrupt Controller */
-#define IOP331_INTCTL0    (volatile u32 *)IOP331_REG_ADDR(0x00000790)
-#define IOP331_INTCTL1    (volatile u32 *)IOP331_REG_ADDR(0x00000794)
-#define IOP331_INTSTR0    (volatile u32 *)IOP331_REG_ADDR(0x00000798)
-#define IOP331_INTSTR1    (volatile u32 *)IOP331_REG_ADDR(0x0000079C)
-#define IOP331_IINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A0)
-#define IOP331_IINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007A4)
-#define IOP331_FINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A8)
-#define IOP331_FINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007AC)
-#define IOP331_IPR0       (volatile u32 *)IOP331_REG_ADDR(0x000007B0)
-#define IOP331_IPR1       (volatile u32 *)IOP331_REG_ADDR(0x000007B4)
-#define IOP331_IPR2       (volatile u32 *)IOP331_REG_ADDR(0x000007B8)
-#define IOP331_IPR3       (volatile u32 *)IOP331_REG_ADDR(0x000007BC)
-#define IOP331_INTBASE    (volatile u32 *)IOP331_REG_ADDR(0x000007C0)
-#define IOP331_INTSIZE    (volatile u32 *)IOP331_REG_ADDR(0x000007C4)
-#define IOP331_IINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007C8)
-#define IOP331_FINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007CC)
-
-
-/* Timers */
-
-#define IOP331_TU_TMR0		(volatile u32 *)IOP331_REG_ADDR(0x000007D0)
-#define IOP331_TU_TMR1		(volatile u32 *)IOP331_REG_ADDR(0x000007D4)
-
-#define IOP331_TMR_TC		0x01
-#define	IOP331_TMR_EN		0x02
-#define IOP331_TMR_RELOAD	0x04
-#define	IOP331_TMR_PRIVILEGED	0x09
-
-#define	IOP331_TMR_RATIO_1_1	0x00
-#define	IOP331_TMR_RATIO_4_1	0x10
-#define	IOP331_TMR_RATIO_8_1	0x20
-#define	IOP331_TMR_RATIO_16_1	0x30
-
-#define IOP331_TU_TCR0    (volatile u32 *)IOP331_REG_ADDR(0x000007D8)
-#define IOP331_TU_TCR1    (volatile u32 *)IOP331_REG_ADDR(0x000007DC)
-#define IOP331_TU_TRR0    (volatile u32 *)IOP331_REG_ADDR(0x000007E0)
-#define IOP331_TU_TRR1    (volatile u32 *)IOP331_REG_ADDR(0x000007E4)
-#define IOP331_TU_TISR    (volatile u32 *)IOP331_REG_ADDR(0x000007E8)
-#define IOP331_TU_WDTCR   (volatile u32 *)IOP331_REG_ADDR(0x000007EC)
-
-#if defined(CONFIG_ARCH_IOP331)
-#define	IOP331_TICK_RATE	266000000	/* 266 MHz IB clock */
-#endif
-
-#if defined(CONFIG_IOP331_STEPD) || defined(CONFIG_ARCH_IQ80333)
-#undef IOP331_TICK_RATE
-#define IOP331_TICK_RATE	333000000	/* 333 Mhz IB clock */
-#endif
-
-/* Application accelerator unit 0x00000800 - 0x000008FF */
-#define IOP331_AAU_ACR     (volatile u32 *)IOP331_REG_ADDR(0x00000800)
-#define IOP331_AAU_ASR     (volatile u32 *)IOP331_REG_ADDR(0x00000804)
-#define IOP331_AAU_ADAR    (volatile u32 *)IOP331_REG_ADDR(0x00000808)
-#define IOP331_AAU_ANDAR   (volatile u32 *)IOP331_REG_ADDR(0x0000080C)
-#define IOP331_AAU_SAR1    (volatile u32 *)IOP331_REG_ADDR(0x00000810)
-#define IOP331_AAU_SAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000814)
-#define IOP331_AAU_SAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000818)
-#define IOP331_AAU_SAR4    (volatile u32 *)IOP331_REG_ADDR(0x0000081C)
-#define IOP331_AAU_SAR5    (volatile u32 *)IOP331_REG_ADDR(0x0000082C)
-#define IOP331_AAU_SAR6    (volatile u32 *)IOP331_REG_ADDR(0x00000830)
-#define IOP331_AAU_SAR7    (volatile u32 *)IOP331_REG_ADDR(0x00000834)
-#define IOP331_AAU_SAR8    (volatile u32 *)IOP331_REG_ADDR(0x00000838)
-#define IOP331_AAU_SAR9    (volatile u32 *)IOP331_REG_ADDR(0x00000840)
-#define IOP331_AAU_SAR10   (volatile u32 *)IOP331_REG_ADDR(0x00000844)
-#define IOP331_AAU_SAR11   (volatile u32 *)IOP331_REG_ADDR(0x00000848)
-#define IOP331_AAU_SAR12   (volatile u32 *)IOP331_REG_ADDR(0x0000084C)
-#define IOP331_AAU_SAR13   (volatile u32 *)IOP331_REG_ADDR(0x00000850)
-#define IOP331_AAU_SAR14   (volatile u32 *)IOP331_REG_ADDR(0x00000854)
-#define IOP331_AAU_SAR15   (volatile u32 *)IOP331_REG_ADDR(0x00000858)
-#define IOP331_AAU_SAR16   (volatile u32 *)IOP331_REG_ADDR(0x0000085C)
-#define IOP331_AAU_SAR17   (volatile u32 *)IOP331_REG_ADDR(0x00000864)
-#define IOP331_AAU_SAR18   (volatile u32 *)IOP331_REG_ADDR(0x00000868)
-#define IOP331_AAU_SAR19   (volatile u32 *)IOP331_REG_ADDR(0x0000086C)
-#define IOP331_AAU_SAR20   (volatile u32 *)IOP331_REG_ADDR(0x00000870)
-#define IOP331_AAU_SAR21   (volatile u32 *)IOP331_REG_ADDR(0x00000874)
-#define IOP331_AAU_SAR22   (volatile u32 *)IOP331_REG_ADDR(0x00000878)
-#define IOP331_AAU_SAR23   (volatile u32 *)IOP331_REG_ADDR(0x0000087C)
-#define IOP331_AAU_SAR24   (volatile u32 *)IOP331_REG_ADDR(0x00000880)
-#define IOP331_AAU_SAR25   (volatile u32 *)IOP331_REG_ADDR(0x00000888)
-#define IOP331_AAU_SAR26   (volatile u32 *)IOP331_REG_ADDR(0x0000088C)
-#define IOP331_AAU_SAR27   (volatile u32 *)IOP331_REG_ADDR(0x00000890)
-#define IOP331_AAU_SAR28   (volatile u32 *)IOP331_REG_ADDR(0x00000894)
-#define IOP331_AAU_SAR29   (volatile u32 *)IOP331_REG_ADDR(0x00000898)
-#define IOP331_AAU_SAR30   (volatile u32 *)IOP331_REG_ADDR(0x0000089C)
-#define IOP331_AAU_SAR31   (volatile u32 *)IOP331_REG_ADDR(0x000008A0)
-#define IOP331_AAU_SAR32   (volatile u32 *)IOP331_REG_ADDR(0x000008A4)
-#define IOP331_AAU_DAR     (volatile u32 *)IOP331_REG_ADDR(0x00000820)
-#define IOP331_AAU_ABCR    (volatile u32 *)IOP331_REG_ADDR(0x00000824)
-#define IOP331_AAU_ADCR    (volatile u32 *)IOP331_REG_ADDR(0x00000828)
-#define IOP331_AAU_EDCR0   (volatile u32 *)IOP331_REG_ADDR(0x0000083c)
-#define IOP331_AAU_EDCR1   (volatile u32 *)IOP331_REG_ADDR(0x00000860)
-#define IOP331_AAU_EDCR2   (volatile u32 *)IOP331_REG_ADDR(0x00000884)
-
-
-#define IOP331_SPDSCR	  (volatile u32 *)IOP331_REG_ADDR(0x000015C0)
-#define IOP331_PPDSCR	  (volatile u32 *)IOP331_REG_ADDR(0x000015C8)
-/* SSP serial port unit 0x00001600 - 0x0000167F */
-
-/* I2C bus interface unit 0x00001680 - 0x000016FF */
-/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
-
-#define IOP331_ICR0       (volatile u32 *)IOP331_REG_ADDR(0x00001680)
-#define IOP331_ISR0       (volatile u32 *)IOP331_REG_ADDR(0x00001684)
-#define IOP331_ISAR0      (volatile u32 *)IOP331_REG_ADDR(0x00001688)
-#define IOP331_IDBR0      (volatile u32 *)IOP331_REG_ADDR(0x0000168C)
-/* Reserved 0x00001690 */
-#define IOP331_IBMR0      (volatile u32 *)IOP331_REG_ADDR(0x00001694)
-/* Reserved 0x00001698 */
-/* Reserved 0x0000169C */
-#define IOP331_ICR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A0)
-#define IOP331_ISR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A4)
-#define IOP331_ISAR1      (volatile u32 *)IOP331_REG_ADDR(0x000016A8)
-#define IOP331_IDBR1      (volatile u32 *)IOP331_REG_ADDR(0x000016AC)
-#define IOP331_IBMR1      (volatile u32 *)IOP331_REG_ADDR(0x000016B4)
-/* Reserved 0x000016B8 through 0x000016FF */
-
-/* 0x00001700 through 0x0000172C  UART 0 */
-
-/* Reserved 0x00001730 through 0x0000173F */
-
-/* 0x00001740 through 0x0000176C UART 1 */
-
-#define IOP331_UART0_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001700)	/* UART #1 physical */
-#define IOP331_UART1_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001740)	/* UART #2 physical */
-#define IOP331_UART0_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001700) /* UART #1 virtual addr */
-#define IOP331_UART1_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001740) /* UART #2 virtual addr */
-
-/* Reserved 0x00001770 through 0x0000177F */
-
-/* General Purpose I/O Registers */
-#define IOP331_GPOE       (volatile u32 *)IOP331_REG_ADDR(0x00001780)
-#define IOP331_GPID       (volatile u32 *)IOP331_REG_ADDR(0x00001784)
-#define IOP331_GPOD       (volatile u32 *)IOP331_REG_ADDR(0x00001788)
-
-/* Reserved 0x0000178c through 0x000019ff */
-
-
-#ifndef __ASSEMBLY__
-extern void iop331_map_io(void);
-extern void iop331_init_irq(void);
-extern void iop331_time_init(void);
-#endif
-
-#endif // _IOP331_HW_H_
diff --git a/include/asm-arm/arch-iop3xx/iq31244.h b/include/asm-arm/arch-iop3xx/iq31244.h
deleted file mode 100644
index 4177cfa..0000000
--- a/include/asm-arm/arch-iop3xx/iq31244.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq31244.h
- *
- * Intel IQ31244 evaluation board registers
- */
-
-#ifndef _IQ31244_H_
-#define _IQ31244_H_
-
-#define	IQ31244_FLASHBASE	0xf0000000	/* Flash */
-#define	IQ31244_FLASHSIZE	0x00800000
-#define	IQ31244_FLASHWIDTH	2
-
-#define IQ31244_UART		0xfe800000	/* UART #1 */
-#define IQ31244_7SEG_1		0xfe840000	/* 7-Segment MSB */
-#define IQ31244_7SEG_0		0xfe850000	/* 7-Segment LSB (WO) */
-#define IQ31244_ROTARY_SW	0xfe8d0000	/* Rotary Switch */
-#define IQ31244_BATT_STAT	0xfe8f0000	/* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq31244_map_io(void);
-#endif
-
-#endif	// _IQ31244_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80321.h b/include/asm-arm/arch-iop3xx/iq80321.h
deleted file mode 100644
index cb87259..0000000
--- a/include/asm-arm/arch-iop3xx/iq80321.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq80321.h
- *
- * Intel IQ80321 evaluation board registers
- */
-
-#ifndef _IQ80321_H_
-#define _IQ80321_H_
-
-#define	IQ80321_FLASHBASE	0xf0000000	/* Flash */
-#define	IQ80321_FLASHSIZE	0x00800000
-#define	IQ80321_FLASHWIDTH	1
-
-#define IQ80321_UART		0xfe800000	/* UART #1 */
-#define IQ80321_7SEG_1		0xfe840000	/* 7-Segment MSB */
-#define IQ80321_7SEG_0		0xfe850000	/* 7-Segment LSB (WO) */
-#define IQ80321_ROTARY_SW	0xfe8d0000	/* Rotary Switch */
-#define IQ80321_BATT_STAT	0xfe8f0000	/* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq80321_map_io(void);
-#endif
-
-#endif	// _IQ80321_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80331.h b/include/asm-arm/arch-iop3xx/iq80331.h
deleted file mode 100644
index 0668e78..0000000
--- a/include/asm-arm/arch-iop3xx/iq80331.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq80331.h
- *
- * Intel IQ80331 evaluation board registers
- */
-
-#ifndef _IQ80331_H_
-#define _IQ80331_H_
-
-#define	IQ80331_FLASHBASE	0xc0000000	/* Flash */
-#define	IQ80331_FLASHSIZE	0x00800000
-#define	IQ80331_FLASHWIDTH	1
-
-#define IQ80331_7SEG_1		0xce840000	/* 7-Segment MSB */
-#define IQ80331_7SEG_0		0xce850000	/* 7-Segment LSB (WO) */
-#define IQ80331_ROTARY_SW	0xce8d0000	/* Rotary Switch */
-#define IQ80331_BATT_STAT	0xce8f0000	/* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq80331_map_io(void);
-#endif
-
-#endif	// _IQ80331_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80332.h b/include/asm-arm/arch-iop3xx/iq80332.h
deleted file mode 100644
index e5fff17..0000000
--- a/include/asm-arm/arch-iop3xx/iq80332.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq80332.h
- *
- * Intel IQ80332 evaluation board registers
- */
-
-#ifndef _IQ80332_H_
-#define _IQ80332_H_
-
-#define	IQ80332_FLASHBASE	0xc0000000	/* Flash */
-#define	IQ80332_FLASHSIZE	0x00800000
-#define	IQ80332_FLASHWIDTH	1
-
-#define IQ80332_7SEG_1		0xce840000	/* 7-Segment MSB */
-#define IQ80332_7SEG_0		0xce850000	/* 7-Segment LSB (WO) */
-#define IQ80332_ROTARY_SW	0xce8d0000	/* Rotary Switch */
-#define IQ80332_BATT_STAT	0xce8f0000	/* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq80332_map_io(void);
-#endif
-
-#endif	// _IQ80332_H_
diff --git a/include/asm-arm/arch-iop3xx/irqs.h b/include/asm-arm/arch-iop3xx/irqs.h
deleted file mode 100644
index b2c03f4..0000000
--- a/include/asm-arm/arch-iop3xx/irqs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/irqs.h
- *
- * Copyright:	(C) 2001-2003 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-/*
- * Chipset-specific bits
- */
-#ifdef CONFIG_ARCH_IOP321
-#include "iop321-irqs.h"
-#endif
-
-#ifdef CONFIG_ARCH_IOP331
-#include "iop331-irqs.h"
-#endif
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
deleted file mode 100644
index e43ebd9..0000000
--- a/include/asm-arm/arch-iop3xx/memory.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/hardware.h>
-
-/*
- * Physical DRAM offset.
- */
-#ifndef CONFIG_ARCH_IOP331
-#define PHYS_OFFSET	UL(0xa0000000)
-#else
-#define PHYS_OFFSET	UL(0x00000000)
-#endif
-
-/*
- * Virtual view <-> PCI DMA view memory address translations
- * virt_to_bus: Used to translate the virtual address to an
- *		address suitable to be passed to set_dma_addr
- * bus_to_virt: Used to convert an address for DMA operations
- *		to an address that the kernel can use.
- */
-#if defined(CONFIG_ARCH_IOP321)
-
-#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP321_IATVR2)) | ((*IOP321_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP321_IALR2)) | ( *IOP321_IATVR2)))
-
-#elif defined(CONFIG_ARCH_IOP331)
-
-#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP331_IATVR2)) | ((*IOP331_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP331_IALR2)) | ( *IOP331_IATVR2)))
-
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-iop3xx/system.h b/include/asm-arm/arch-iop3xx/system.h
deleted file mode 100644
index af6ae8c..0000000
--- a/include/asm-arm/arch-iop3xx/system.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/system.h
- *
- *  Copyright (C) 2001 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle();
-}
-
-
-static inline void arch_reset(char mode)
-{
-#ifdef CONFIG_ARCH_IOP321
-    *IOP321_PCSR = 0x30;
-#endif
-
-#ifdef CONFIG_ARCH_IOP331
-    *IOP331_PCSR = 0x30;
-#endif
-
-	if ( 1 && mode == 's') {
-		/* Jump into ROM at address 0 */
-		cpu_reset(0);
-	} else {
-		/* No on-chip reset capability */
-		cpu_reset(0);
-	}
-}
-
diff --git a/include/asm-arm/arch-iop3xx/timex.h b/include/asm-arm/arch-iop3xx/timex.h
deleted file mode 100644
index 14ca8d0..0000000
--- a/include/asm-arm/arch-iop3xx/timex.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/timex.h
- *
- * IOP3xx architecture timex specifications
- */
-#include <asm/hardware.h>
-
-#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
-
-#define CLOCK_TICK_RATE IOP321_TICK_RATE
-
-#elif defined(CONFIG_ARCH_IQ80331) || defined(CONFIG_MACH_IQ80332)
-
-#define CLOCK_TICK_RATE IOP331_TICK_RATE
-
-#else
-
-#error "No IOP3xx timex information for this architecture"
-
-#endif
diff --git a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h
deleted file mode 100644
index fbdd5af..0000000
--- a/include/asm-arm/arch-iop3xx/uncompress.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-iop3xx/uncompress.h
- */
-#include <asm/types.h>
-#include <asm/mach-types.h>
-#include <linux/serial_reg.h>
-#include <asm/hardware.h>
-
-#ifdef CONFIG_ARCH_IOP321
-#define UTYPE unsigned char *
-#elif defined(CONFIG_ARCH_IOP331)
-#define UTYPE u32 *
-#else
-#error "Missing IOP3xx arch type def"
-#endif
-
-static volatile UTYPE uart_base;
-
-#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
-
-static inline void putc(char c)
-{
-	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
-		barrier();
-	*uart_base = c;
-}
-
-static inline void flush(void)
-{
-}
-
-static __inline__ void __arch_decomp_setup(unsigned long arch_id)
-{
-        if(machine_is_iq80321())
-			uart_base = (volatile UTYPE)IQ80321_UART;
-		else if(machine_is_iq31244())
-			uart_base = (volatile UTYPE)IQ31244_UART;
-		else if(machine_is_iq80331() || machine_is_iq80332())
-			uart_base = (volatile UTYPE)IOP331_UART0_PHYS;
-		else
-			uart_base = (volatile UTYPE)0xfe800000;
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
-#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop3xx/vmalloc.h b/include/asm-arm/arch-iop3xx/vmalloc.h
deleted file mode 100644
index 0f2f684..0000000
--- a/include/asm-arm/arch-iop3xx/vmalloc.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/vmalloc.h
- */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-//#define VMALLOC_END       (0xe8000000)
-/* increase usable physical RAM to ~992M per RMK */
-#define VMALLOC_END       (0xfe000000)
-
diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
index 13aee17..8d10a91 100644
--- a/include/asm-arm/arch-ixp4xx/platform.h
+++ b/include/asm-arm/arch-ixp4xx/platform.h
@@ -90,6 +90,11 @@
 struct sys_timer;
 
 /*
+ * Frequency of clock used for primary clocksource
+ */
+extern unsigned long ixp4xx_timer_freq;
+
+/*
  * Functions used by platform-level setup code
  */
 extern void ixp4xx_map_io(void);
diff --git a/include/asm-arm/arch-l7200/io.h b/include/asm-arm/arch-l7200/io.h
index cd080d8..d744d97 100644
--- a/include/asm-arm/arch-l7200/io.h
+++ b/include/asm-arm/arch-l7200/io.h
@@ -31,9 +31,9 @@
 static inline unsigned int __arch_getw(unsigned long a)
 {
 	unsigned int value;
-	__asm__ __volatile__("ldr%?h    %0, [%1, #0]    @ getw"
+	__asm__ __volatile__("ldrh    %0, [%1, #0]    @ getw"
 		: "=&r" (value)
-		: "r" (a));
+		: "r" (a) : "cc");
 	return value;
 }
 
@@ -42,8 +42,8 @@
 
 static inline void __arch_putw(unsigned int value, unsigned long a)
 {
-        __asm__ __volatile__("str%?h    %0, [%1, #0]    @ putw"
-                : : "r" (value), "r" (a));
+        __asm__ __volatile__("strh    %0, [%1, #0]    @ putw"
+                : : "r" (value), "r" (a) : "cc");
 }
 
 /*
diff --git a/include/asm-arm/arch-l7200/time.h b/include/asm-arm/arch-l7200/time.h
index 7b98b53..c69cb50 100644
--- a/include/asm-arm/arch-l7200/time.h
+++ b/include/asm-arm/arch-l7200/time.h
@@ -45,7 +45,7 @@
 static irqreturn_t
 timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/include/asm-arm/arch-omap/board-ams-delta.h b/include/asm-arm/arch-omap/board-ams-delta.h
index 0070f6d..9aee15d 100644
--- a/include/asm-arm/arch-omap/board-ams-delta.h
+++ b/include/asm-arm/arch-omap/board-ams-delta.h
@@ -50,9 +50,20 @@
 #define AMS_DELTA_LATCH2_NAND_NWE	0x0020
 #define AMS_DELTA_LATCH2_NAND_ALE	0x0040
 #define AMS_DELTA_LATCH2_NAND_CLE	0x0080
+#define AMD_DELTA_LATCH2_KEYBRD_PWR	0x0100
+#define AMD_DELTA_LATCH2_KEYBRD_DATA	0x0200
+#define AMD_DELTA_LATCH2_SCARD_RSTIN	0x0400
+#define AMD_DELTA_LATCH2_SCARD_CMDVCC	0x0800
 #define AMS_DELTA_LATCH2_MODEM_NRESET	0x1000
 #define AMS_DELTA_LATCH2_MODEM_CODEC	0x2000
 
+#define AMS_DELTA_GPIO_PIN_KEYBRD_DATA	0
+#define AMS_DELTA_GPIO_PIN_KEYBRD_CLK	1
+#define AMS_DELTA_GPIO_PIN_MODEM_IRQ	2
+#define AMS_DELTA_GPIO_PIN_HOOK_SWITCH	4
+#define AMS_DELTA_GPIO_PIN_SCARD_NOFF	6
+#define AMS_DELTA_GPIO_PIN_SCARD_IO	7
+#define AMS_DELTA_GPIO_PIN_CONFIG	11
 #define AMS_DELTA_GPIO_PIN_NAND_RB	12
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index f83003f..fa68810 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -45,6 +45,7 @@
 	struct clk *	(*clk_get_parent)(struct clk *clk);
 	void		(*clk_allow_idle)(struct clk *clk);
 	void		(*clk_deny_idle)(struct clk *clk);
+	void		(*clk_disable_unused)(struct clk *clk);
 };
 
 extern unsigned int mpurate;
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index 1b1b023..d591d05 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -331,6 +331,12 @@
 	OMAP_DMA_TRANSPARENT_COPY
 };
 
+enum omap_dma_write_mode {
+	OMAP_DMA_WRITE_NON_POSTED = 0,
+	OMAP_DMA_WRITE_POSTED,
+	OMAP_DMA_WRITE_LAST_NON_POSTED
+};
+
 struct omap_dma_channel_params {
 	int data_type;		/* data type 8,16,32 */
 	int elem_count;		/* number of elements in a frame */
@@ -338,13 +344,13 @@
 
 	int src_port;		/* Only on OMAP1 REVISIT: Is this needed? */
 	int src_amode;		/* constant , post increment, indexed , double indexed */
-	int src_start;		/* source address : physical */
+	unsigned long src_start;	/* source address : physical */
 	int src_ei;		/* source element index */
 	int src_fi;		/* source frame index */
 
 	int dst_port;		/* Only on OMAP1 REVISIT: Is this needed? */
 	int dst_amode;		/* constant , post increment, indexed , double indexed */
-	int dst_start;		/* source address : physical */
+	unsigned long dst_start;	/* source address : physical */
 	int dst_ei;		/* source element index */
 	int dst_fi;		/* source frame index */
 
@@ -356,7 +362,7 @@
 };
 
 
-extern void omap_set_dma_priority(int dst_port, int priority);
+extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
 			    void (* callback)(int lch, u16 ch_status, void *data),
 			    void *data, int *dma_ch);
@@ -371,6 +377,7 @@
 					 int dma_trigger, int src_or_dst_synch);
 extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
 				    u32 color);
+extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
 
 extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 				    unsigned long src_start,
@@ -394,6 +401,9 @@
 extern void omap_dma_link_lch (int lch_head, int lch_queue);
 extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
 
+extern int omap_set_dma_callback(int lch,
+			void (* callback)(int lch, u16 ch_status, void *data),
+			void *data);
 extern dma_addr_t omap_get_dma_src_pos(int lch);
 extern dma_addr_t omap_get_dma_dst_pos(int lch);
 extern int omap_get_dma_src_addr_counter(int lch);
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
index 7a289ff..b5f3a71 100644
--- a/include/asm-arm/arch-omap/dmtimer.h
+++ b/include/asm-arm/arch-omap/dmtimer.h
@@ -52,6 +52,8 @@
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
 void omap_dm_timer_free(struct omap_dm_timer *timer);
+void omap_dm_timer_enable(struct omap_dm_timer *timer);
+void omap_dm_timer_disable(struct omap_dm_timer *timer);
 
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
 
diff --git a/include/asm-arm/arch-omap/gpmc.h b/include/asm-arm/arch-omap/gpmc.h
index 1a0a520..7c03ef6 100644
--- a/include/asm-arm/arch-omap/gpmc.h
+++ b/include/asm-arm/arch-omap/gpmc.h
@@ -85,7 +85,7 @@
 extern u32 gpmc_cs_read_reg(int cs, int idx);
 extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
 extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
-extern unsigned long gpmc_cs_get_base_addr(int cs);
-
+extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+extern void gpmc_cs_free(int cs);
 
 #endif
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index 2542495..c5bb05a 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -237,6 +237,7 @@
 #define INT_24XX_SDMA_IRQ1	13
 #define INT_24XX_SDMA_IRQ2	14
 #define INT_24XX_SDMA_IRQ3	15
+#define INT_24XX_CAM_IRQ	24
 #define INT_24XX_DSS_IRQ	25
 #define INT_24XX_GPIO_BANK1	29
 #define INT_24XX_GPIO_BANK2	30
@@ -261,6 +262,7 @@
 #define INT_24XX_UART1_IRQ	72
 #define INT_24XX_UART2_IRQ	73
 #define INT_24XX_UART3_IRQ	74
+#define INT_24XX_MMC_IRQ	83
 
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
  * 16 MPUIO lines */
diff --git a/include/asm-arm/arch-omap/keypad.h b/include/asm-arm/arch-omap/keypad.h
index 8a023a9..b7f8307 100644
--- a/include/asm-arm/arch-omap/keypad.h
+++ b/include/asm-arm/arch-omap/keypad.h
@@ -14,7 +14,10 @@
 	int rows;
 	int cols;
 	int *keymap;
+	unsigned int keymapsize;
 	unsigned int rep:1;
+	unsigned long delay;
+	unsigned int dbounce:1;
 	/* specific to OMAP242x*/
 	unsigned int *row_gpios;
 	unsigned int *col_gpios;
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index 679869c..828cc5c 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -320,6 +320,17 @@
 	P15_1610_UWIRE_CS3,
 	N15_1610_UWIRE_CS1,
 
+	/* OMAP-1610 SPI */
+	U19_1610_SPIF_SCK,
+	U18_1610_SPIF_DIN,
+	P20_1610_SPIF_DIN,
+	W21_1610_SPIF_DOUT,
+	R18_1610_SPIF_DOUT,
+	N14_1610_SPIF_CS0,
+	N15_1610_SPIF_CS1,
+	T19_1610_SPIF_CS2,
+	P15_1610_SPIF_CS3,
+
 	/* OMAP-1610 Flash */
 	L3_1610_FLASH_CS2B_OE,
 	M8_1610_FLASH_CS2B_WE,
@@ -461,6 +472,20 @@
 	K15_24XX_UART3_TX,
 	K14_24XX_UART3_RX,
 
+	/* MMC/SDIO */
+	G19_24XX_MMC_CLKO,
+	H18_24XX_MMC_CMD,
+	F20_24XX_MMC_DAT0,
+	H14_24XX_MMC_DAT1,
+	E19_24XX_MMC_DAT2,
+	D19_24XX_MMC_DAT3,
+	F19_24XX_MMC_DAT_DIR0,
+	E20_24XX_MMC_DAT_DIR1,
+	F18_24XX_MMC_DAT_DIR2,
+	E18_24XX_MMC_DAT_DIR3,
+	G18_24XX_MMC_CMD_DIR,
+	H15_24XX_MMC_CLKI,
+
 	/* Keypad GPIO*/
 	T19_24XX_KBR0,
 	R19_24XX_KBR1,
diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h
index 30548a3..121cd24 100644
--- a/include/asm-arm/arch-pxa/udc.h
+++ b/include/asm-arm/arch-pxa/udc.h
@@ -12,6 +12,14 @@
         void (*udc_command)(int cmd);
 #define	PXA2XX_UDC_CMD_CONNECT		0	/* let host see us */
 #define	PXA2XX_UDC_CMD_DISCONNECT	1	/* so host won't see us */
+
+	/* Boards following the design guidelines in the developer's manual,
+	 * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
+	 * VBUS IRQ and omit the methods above.  Store the GPIO number
+	 * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
+	 */
+	u16	gpio_vbus;			/* high == vbus present */
+	u16	gpio_pullup;			/* high == pullup activated */
 };
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index 3661e46..7ac2248 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -23,6 +23,39 @@
 #define MAX_DMA_ADDRESS		0x40000000
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
+/* We use `virtual` dma channels to hide the fact we have only a limited
+ * number of DMA channels, and not of all of them (dependant on the device)
+ * can be attached to any DMA source. We therefore let the DMA core handle
+ * the allocation of hardware channels to clients.
+*/
+
+enum dma_ch {
+	DMACH_XD0,
+	DMACH_XD1,
+	DMACH_SDI,
+	DMACH_SPI0,
+	DMACH_SPI1,
+	DMACH_UART0,
+	DMACH_UART1,
+	DMACH_UART2,
+	DMACH_TIMER,
+	DMACH_I2S_IN,
+	DMACH_I2S_OUT,
+	DMACH_PCM_IN,
+	DMACH_PCM_OUT,
+	DMACH_MIC_IN,
+	DMACH_USB_EP1,
+	DMACH_USB_EP2,
+	DMACH_USB_EP3,
+	DMACH_USB_EP4,
+	DMACH_UART0_SRC2,	/* s3c2412 second uart sources */
+	DMACH_UART1_SRC2,
+	DMACH_UART2_SRC2,
+	DMACH_MAX,		/* the end entry */
+};
+
+#define DMACH_LOW_LEVEL	(1<<28)	/* use this to specifiy hardware ch no */
+
 /* we have 4 dma channels */
 #define S3C2410_DMA_CHANNELS        (4)
 
@@ -149,6 +182,8 @@
 	unsigned long		timeout_failed;
 };
 
+struct s3c2410_dma_map;
+
 /* struct s3c2410_dma_chan
  *
  * full state information for each DMA channel
@@ -174,6 +209,8 @@
 	unsigned long		 load_timeout;
 	unsigned int		 flags;		/* channel flags */
 
+	struct s3c24xx_dma_map	*map;		/* channel hw maps */
+
 	/* channel's hardware position and configuration */
 	void __iomem		*regs;		/* channels registers */
 	void __iomem		*addr_reg;	/* data address register */
@@ -283,6 +320,7 @@
 #define S3C2410_DMA_DCSRC       (0x18)
 #define S3C2410_DMA_DCDST       (0x1C)
 #define S3C2410_DMA_DMASKTRIG   (0x20)
+#define S3C2412_DMA_DMAREQSEL	(0x24)
 
 #define S3C2410_DISRCC_INC	(1<<0)
 #define S3C2410_DISRCC_APB	(1<<1)
@@ -349,4 +387,32 @@
 #define S3C2440_DCON_CH3_PCMOUT	(6<<24)
 #endif
 
+#ifdef CONFIG_CPU_S3C2412
+
+#define S3C2412_DMAREQSEL_SRC(x)	((x)<<1)
+
+#define S3C2412_DMAREQSEL_HW		(1)
+
+#define S3C2412_DMAREQSEL_SPI0TX	S3C2412_DMAREQSEL_SRC(0)
+#define S3C2412_DMAREQSEL_SPI0RX	S3C2412_DMAREQSEL_SRC(1)
+#define S3C2412_DMAREQSEL_SPI1TX	S3C2412_DMAREQSEL_SRC(2)
+#define S3C2412_DMAREQSEL_SPI1RX	S3C2412_DMAREQSEL_SRC(3)
+#define S3C2412_DMAREQSEL_I2STX		S3C2412_DMAREQSEL_SRC(4)
+#define S3C2412_DMAREQSEL_I2SRX		S3C2412_DMAREQSEL_SRC(5)
+#define S3C2412_DMAREQSEL_TIMER		S3C2412_DMAREQSEL_SRC(9)
+#define S3C2412_DMAREQSEL_SDI		S3C2412_DMAREQSEL_SRC(10)
+#define S3C2412_DMAREQSEL_USBEP1	S3C2412_DMAREQSEL_SRC(13)
+#define S3C2412_DMAREQSEL_USBEP2	S3C2412_DMAREQSEL_SRC(14)
+#define S3C2412_DMAREQSEL_USBEP3	S3C2412_DMAREQSEL_SRC(15)
+#define S3C2412_DMAREQSEL_USBEP4	S3C2412_DMAREQSEL_SRC(16)
+#define S3C2412_DMAREQSEL_XDREQ0	S3C2412_DMAREQSEL_SRC(17)
+#define S3C2412_DMAREQSEL_XDREQ1	S3C2412_DMAREQSEL_SRC(18)
+#define S3C2412_DMAREQSEL_UART0_0	S3C2412_DMAREQSEL_SRC(19)
+#define S3C2412_DMAREQSEL_UART0_1	S3C2412_DMAREQSEL_SRC(20)
+#define S3C2412_DMAREQSEL_UART1_0	S3C2412_DMAREQSEL_SRC(21)
+#define S3C2412_DMAREQSEL_UART1_1	S3C2412_DMAREQSEL_SRC(22)
+#define S3C2412_DMAREQSEL_UART2_0	S3C2412_DMAREQSEL_SRC(23)
+#define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
+
+#endif
 #endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index 27ba0ac..7895042 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -160,6 +160,11 @@
 #define S3C2440_PA_CAMIF   (0x4F000000)
 #define S3C2440_SZ_CAMIF   SZ_1M
 
+/* AC97 */
+
+#define S3C2440_PA_AC97	   (0x5B000000)
+#define S3C2440_SZ_AC97	   SZ_1M
+
 /* ISA style IO, for each machine to sort out mappings for, if it
  * implements it. We reserve two 16M regions for ISA.
  */
diff --git a/include/asm-arm/arch-s3c2410/osiris-map.h b/include/asm-arm/arch-s3c2410/osiris-map.h
index e2d4062..a14164d 100644
--- a/include/asm-arm/arch-s3c2410/osiris-map.h
+++ b/include/asm-arm/arch-s3c2410/osiris-map.h
@@ -18,22 +18,22 @@
 
 /* start peripherals off after the S3C2410 */
 
-#define OSIRIS_IOADDR(x)	(S3C2410_ADDR((x) + 0x05000000))
+#define OSIRIS_IOADDR(x)	(S3C2410_ADDR((x) + 0x04000000))
 
-#define OSIRIS_PA_CPLD		(S3C2410_CS1 | (3<<25))
+#define OSIRIS_PA_CPLD		(S3C2410_CS1 | (1<<26))
 
 /* we put the CPLD registers next, to get them out of the way */
 
-#define OSIRIS_VA_CTRL1	    OSIRIS_IOADDR(0x00000000)	 /* 0x01300000 */
+#define OSIRIS_VA_CTRL1	    OSIRIS_IOADDR(0x00000000)
 #define OSIRIS_PA_CTRL1	    (OSIRIS_PA_CPLD)
 
-#define OSIRIS_VA_CTRL2	    OSIRIS_IOADDR(0x00100000)	 /* 0x01400000 */
-#define OSIRIS_PA_CTRL2	    (OSIRIS_PA_CPLD + (1<<24))
+#define OSIRIS_VA_CTRL2	    OSIRIS_IOADDR(0x00100000)
+#define OSIRIS_PA_CTRL2	    (OSIRIS_PA_CPLD + (1<<23))
 
-#define OSIRIS_VA_CTRL3	    OSIRIS_IOADDR(0x00200000)	 /* 0x01500000 */
-#define OSIRIS_PA_CTRL3	    (OSIRIS_PA_CPLD + (2<<24))
+#define OSIRIS_VA_CTRL3	    OSIRIS_IOADDR(0x00200000)
+#define OSIRIS_PA_CTRL3	    (OSIRIS_PA_CPLD + (2<<23))
 
-#define OSIRIS_VA_CTRL4	    OSIRIS_IOADDR(0x00300000)	 /* 0x01600000 */
-#define OSIRIS_PA_CTRL4	    (OSIRIS_PA_CPLD + (3<<24))
+#define OSIRIS_VA_CTRL4	    OSIRIS_IOADDR(0x00300000)
+#define OSIRIS_PA_CTRL4	    (OSIRIS_PA_CPLD + (3<<23))
 
 #endif /* __ASM_ARCH_OSIRISMAP_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-ac97.h b/include/asm-arm/arch-s3c2410/regs-ac97.h
new file mode 100644
index 0000000..bdd6a4f
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/regs-ac97.h
@@ -0,0 +1,23 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-ac97.h
+ *
+ * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk>
+ *		http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2440 AC97 Controller
+*/
+
+#ifndef __ASM_ARCH_REGS_AC97_H
+#define __ASM_ARCH_REGS_AC97_H __FILE__
+
+#define S3C_AC97_GLBCTRL	(0x00)
+#define S3C_AC97_GLBSTAT	(0x04)
+#define S3C_AC97_CODEC_CMD	(0x08)
+#define S3C_AC97_PCM_ADDR	(0x10)
+#define S3C_AC97_PCM_DATA	(0x18)
+#define S3C_AC97_MIC_DATA	(0x1C)
+
+#endif /* __ASM_ARCH_REGS_AC97_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
index b306d6e..6d7881c 100644
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h
@@ -63,6 +63,8 @@
 #define S3C2410_LCDCON3_GET_HBPD(x) ( ((x) >> 19) & 0x7F)
 #define S3C2410_LCDCON3_GET_HFPD(x) ( ((x) >>  0) & 0xFF)
 
+/* LDCCON4 changes for STN mode on the S3C2412 */
+
 #define S3C2410_LCDCON4_MVAL(x)	    ((x) << 8)
 #define S3C2410_LCDCON4_HSPW(x)	    ((x) << 0)
 #define S3C2410_LCDCON4_WLH(x)	    ((x) << 0)
@@ -113,10 +115,38 @@
 #define	S3C2410_LCDINT_FRSYNC	(1<<1)
 #define S3C2410_LCDINT_FICNT	(1<<0)
 
+/* s3c2442 extra stn registers */
+
+#define S3C2442_REDLUT		S3C2410_LCDREG(0x20)
+#define S3C2442_GREENLUT	S3C2410_LCDREG(0x24)
+#define S3C2442_BLUELUT		S3C2410_LCDREG(0x28)
+#define S3C2442_DITHMODE	S3C2410_LCDREG(0x20)
+
 #define S3C2410_LPCSEL	   S3C2410_LCDREG(0x60)
 
 #define S3C2410_TFTPAL(x)  S3C2410_LCDREG((0x400 + (x)*4))
 
+/* S3C2412 registers */
+
+#define S3C2412_TPAL		S3C2410_LCDREG(0x20)
+
+#define S3C2412_LCDINTPND	S3C2410_LCDREG(0x24)
+#define S3C2412_LCDSRCPND	S3C2410_LCDREG(0x28)
+#define S3C2412_LCDINTMSK	S3C2410_LCDREG(0x2C)
+
+#define S3C2412_TCONSEL		S3C2410_LCDREG(0x30)
+
+#define S3C2412_LCDCON6		S3C2410_LCDREG(0x34)
+#define S3C2412_LCDCON7		S3C2410_LCDREG(0x38)
+#define S3C2412_LCDCON8		S3C2410_LCDREG(0x3C)
+#define S3C2412_LCDCON9		S3C2410_LCDREG(0x40)
+
+#define S3C2412_REDLUT(x)	S3C2410_LCDREG(0x44 + ((x)*4))
+#define S3C2412_GREENLUT(x)	S3C2410_LCDREG(0x60 + ((x)*4))
+#define S3C2412_BLUELUT(x)	S3C2410_LCDREG(0x98 + ((x)*4))
+
+#define S3C2412_FRCPAT(x)	S3C2410_LCDREG(0xB4 + ((x)*4))
+
 #endif /* ___ASM_ARCH_REGS_LCD_H */
 
 
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index 4b0ce3e..ea88aa6 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -128,10 +128,10 @@
 	unsigned long flags;
 	int val;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	val = v->counter;
 	v->counter = val += i;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return val;
 }
@@ -141,10 +141,10 @@
 	unsigned long flags;
 	int val;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	val = v->counter;
 	v->counter = val -= i;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return val;
 }
@@ -154,11 +154,11 @@
 	int ret;
 	unsigned long flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	ret = v->counter;
 	if (likely(ret == old))
 		v->counter = new;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return ret;
 }
@@ -167,9 +167,9 @@
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	*addr &= ~mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 #endif /* __LINUX_ARM_ARCH__ */
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index 0ac54b1..b41831b6 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -37,9 +37,9 @@
 
 	p += bit >> 5;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	*p |= mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
@@ -49,9 +49,9 @@
 
 	p += bit >> 5;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	*p &= ~mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
@@ -61,9 +61,9 @@
 
 	p += bit >> 5;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	*p ^= mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 static inline int
@@ -75,10 +75,10 @@
 
 	p += bit >> 5;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	res = *p;
 	*p = res | mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return res & mask;
 }
@@ -92,10 +92,10 @@
 
 	p += bit >> 5;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	res = *p;
 	*p = res & ~mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return res & mask;
 }
@@ -109,10 +109,10 @@
 
 	p += bit >> 5;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	res = *p;
 	*p = res ^ mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return res & mask;
 }
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index e4a2569..f084564 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -25,7 +25,7 @@
 #undef _CACHE
 #undef MULTI_CACHE
 
-#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+#if defined(CONFIG_CPU_CACHE_V3)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
 # else
@@ -33,7 +33,7 @@
 # endif
 #endif
 
-#if defined(CONFIG_CPU_ARM720T)
+#if defined(CONFIG_CPU_CACHE_V4)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
 # else
@@ -54,7 +54,23 @@
 # endif
 #endif
 
-#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
+#if defined(CONFIG_CPU_ARM940T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm940
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM946E)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm946
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4WB)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
 # else
diff --git a/include/asm-arm/flat.h b/include/asm-arm/flat.h
new file mode 100644
index 0000000..9669464
--- /dev/null
+++ b/include/asm-arm/flat.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/flat.h -- uClinux flat-format executables
+ */
+
+#ifndef __ARM_FLAT_H__
+#define __ARM_FLAT_H__
+
+#define	flat_stack_align(sp)			/* nothing needed */
+#define	flat_argvp_envp_on_stack()		1
+#define	flat_old_ram_flag(flags)		(flags)
+#define	flat_reloc_valid(reloc, size)		((reloc) <= (size))
+#define	flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp)
+#define	flat_put_addr_at_rp(rp, val, relval)	put_unaligned(val,rp)
+#define	flat_get_relocate_addr(rel)		(rel)
+
+#endif /* __ARM_FLAT_H__ */
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
new file mode 100644
index 0000000..1018a74
--- /dev/null
+++ b/include/asm-arm/hardware/iop3xx.h
@@ -0,0 +1,301 @@
+/*
+ * include/asm-arm/hardware/iop3xx.h
+ *
+ * Intel IOP32X and IOP33X register definitions
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __IOP3XX_H
+#define __IOP3XX_H
+
+/*
+ * IOP3XX GPIO handling
+ */
+#define GPIO_IN			0
+#define GPIO_OUT		1
+#define GPIO_LOW		0
+#define GPIO_HIGH		1
+#define IOP3XX_GPIO_LINE(x)	(x)
+
+#ifndef __ASSEMBLY__
+extern void gpio_line_config(int line, int direction);
+extern int  gpio_line_get(int line);
+extern void gpio_line_set(int line, int value);
+#endif
+
+
+/*
+ * IOP3XX processor registers
+ */
+#define IOP3XX_PERIPHERAL_PHYS_BASE	0xffffe000
+#define IOP3XX_PERIPHERAL_VIRT_BASE	0xfeffe000
+#define IOP3XX_PERIPHERAL_SIZE		0x00002000
+#define IOP3XX_REG_ADDR(reg)		(IOP3XX_PERIPHERAL_VIRT_BASE + (reg))
+
+/* Address Translation Unit  */
+#define IOP3XX_ATUVID		(volatile u16 *)IOP3XX_REG_ADDR(0x0100)
+#define IOP3XX_ATUDID		(volatile u16 *)IOP3XX_REG_ADDR(0x0102)
+#define IOP3XX_ATUCMD		(volatile u16 *)IOP3XX_REG_ADDR(0x0104)
+#define IOP3XX_ATUSR		(volatile u16 *)IOP3XX_REG_ADDR(0x0106)
+#define IOP3XX_ATURID		(volatile u8  *)IOP3XX_REG_ADDR(0x0108)
+#define IOP3XX_ATUCCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0109)
+#define IOP3XX_ATUCLSR		(volatile u8  *)IOP3XX_REG_ADDR(0x010c)
+#define IOP3XX_ATULT		(volatile u8  *)IOP3XX_REG_ADDR(0x010d)
+#define IOP3XX_ATUHTR		(volatile u8  *)IOP3XX_REG_ADDR(0x010e)
+#define IOP3XX_ATUBIST		(volatile u8  *)IOP3XX_REG_ADDR(0x010f)
+#define IOP3XX_IABAR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0110)
+#define IOP3XX_IAUBAR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0114)
+#define IOP3XX_IABAR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0118)
+#define IOP3XX_IAUBAR1		(volatile u32 *)IOP3XX_REG_ADDR(0x011c)
+#define IOP3XX_IABAR2		(volatile u32 *)IOP3XX_REG_ADDR(0x0120)
+#define IOP3XX_IAUBAR2		(volatile u32 *)IOP3XX_REG_ADDR(0x0124)
+#define IOP3XX_ASVIR		(volatile u16 *)IOP3XX_REG_ADDR(0x012c)
+#define IOP3XX_ASIR		(volatile u16 *)IOP3XX_REG_ADDR(0x012e)
+#define IOP3XX_ERBAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0130)
+#define IOP3XX_ATUILR		(volatile u8  *)IOP3XX_REG_ADDR(0x013c)
+#define IOP3XX_ATUIPR		(volatile u8  *)IOP3XX_REG_ADDR(0x013d)
+#define IOP3XX_ATUMGNT		(volatile u8  *)IOP3XX_REG_ADDR(0x013e)
+#define IOP3XX_ATUMLAT		(volatile u8  *)IOP3XX_REG_ADDR(0x013f)
+#define IOP3XX_IALR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0140)
+#define IOP3XX_IATVR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0144)
+#define IOP3XX_ERLR		(volatile u32 *)IOP3XX_REG_ADDR(0x0148)
+#define IOP3XX_ERTVR		(volatile u32 *)IOP3XX_REG_ADDR(0x014c)
+#define IOP3XX_IALR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0150)
+#define IOP3XX_IALR2		(volatile u32 *)IOP3XX_REG_ADDR(0x0154)
+#define IOP3XX_IATVR2		(volatile u32 *)IOP3XX_REG_ADDR(0x0158)
+#define IOP3XX_OIOWTVR		(volatile u32 *)IOP3XX_REG_ADDR(0x015c)
+#define IOP3XX_OMWTVR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0160)
+#define IOP3XX_OUMWTVR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0164)
+#define IOP3XX_OMWTVR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0168)
+#define IOP3XX_OUMWTVR1		(volatile u32 *)IOP3XX_REG_ADDR(0x016c)
+#define IOP3XX_OUDWTVR		(volatile u32 *)IOP3XX_REG_ADDR(0x0178)
+#define IOP3XX_ATUCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0180)
+#define IOP3XX_PCSR		(volatile u32 *)IOP3XX_REG_ADDR(0x0184)
+#define IOP3XX_ATUISR		(volatile u32 *)IOP3XX_REG_ADDR(0x0188)
+#define IOP3XX_ATUIMR		(volatile u32 *)IOP3XX_REG_ADDR(0x018c)
+#define IOP3XX_IABAR3		(volatile u32 *)IOP3XX_REG_ADDR(0x0190)
+#define IOP3XX_IAUBAR3		(volatile u32 *)IOP3XX_REG_ADDR(0x0194)
+#define IOP3XX_IALR3		(volatile u32 *)IOP3XX_REG_ADDR(0x0198)
+#define IOP3XX_IATVR3		(volatile u32 *)IOP3XX_REG_ADDR(0x019c)
+#define IOP3XX_OCCAR		(volatile u32 *)IOP3XX_REG_ADDR(0x01a4)
+#define IOP3XX_OCCDR		(volatile u32 *)IOP3XX_REG_ADDR(0x01ac)
+#define IOP3XX_PDSCR		(volatile u32 *)IOP3XX_REG_ADDR(0x01bc)
+#define IOP3XX_PMCAPID		(volatile u8  *)IOP3XX_REG_ADDR(0x01c0)
+#define IOP3XX_PMNEXT		(volatile u8  *)IOP3XX_REG_ADDR(0x01c1)
+#define IOP3XX_APMCR		(volatile u16 *)IOP3XX_REG_ADDR(0x01c2)
+#define IOP3XX_APMCSR		(volatile u16 *)IOP3XX_REG_ADDR(0x01c4)
+#define IOP3XX_PCIXCAPID	(volatile u8  *)IOP3XX_REG_ADDR(0x01e0)
+#define IOP3XX_PCIXNEXT		(volatile u8  *)IOP3XX_REG_ADDR(0x01e1)
+#define IOP3XX_PCIXCMD		(volatile u16 *)IOP3XX_REG_ADDR(0x01e2)
+#define IOP3XX_PCIXSR		(volatile u32 *)IOP3XX_REG_ADDR(0x01e4)
+#define IOP3XX_PCIIRSR		(volatile u32 *)IOP3XX_REG_ADDR(0x01ec)
+
+/* Messaging Unit  */
+#define IOP3XX_IMR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0310)
+#define IOP3XX_IMR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0314)
+#define IOP3XX_OMR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0318)
+#define IOP3XX_OMR1		(volatile u32 *)IOP3XX_REG_ADDR(0x031c)
+#define IOP3XX_IDR		(volatile u32 *)IOP3XX_REG_ADDR(0x0320)
+#define IOP3XX_IISR		(volatile u32 *)IOP3XX_REG_ADDR(0x0324)
+#define IOP3XX_IIMR		(volatile u32 *)IOP3XX_REG_ADDR(0x0328)
+#define IOP3XX_ODR		(volatile u32 *)IOP3XX_REG_ADDR(0x032c)
+#define IOP3XX_OISR		(volatile u32 *)IOP3XX_REG_ADDR(0x0330)
+#define IOP3XX_OIMR		(volatile u32 *)IOP3XX_REG_ADDR(0x0334)
+#define IOP3XX_MUCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0350)
+#define IOP3XX_QBAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0354)
+#define IOP3XX_IFHPR		(volatile u32 *)IOP3XX_REG_ADDR(0x0360)
+#define IOP3XX_IFTPR		(volatile u32 *)IOP3XX_REG_ADDR(0x0364)
+#define IOP3XX_IPHPR		(volatile u32 *)IOP3XX_REG_ADDR(0x0368)
+#define IOP3XX_IPTPR		(volatile u32 *)IOP3XX_REG_ADDR(0x036c)
+#define IOP3XX_OFHPR		(volatile u32 *)IOP3XX_REG_ADDR(0x0370)
+#define IOP3XX_OFTPR		(volatile u32 *)IOP3XX_REG_ADDR(0x0374)
+#define IOP3XX_OPHPR		(volatile u32 *)IOP3XX_REG_ADDR(0x0378)
+#define IOP3XX_OPTPR		(volatile u32 *)IOP3XX_REG_ADDR(0x037c)
+#define IOP3XX_IAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0380)
+
+/* DMA Controller  */
+#define IOP3XX_DMA0_CCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0400)
+#define IOP3XX_DMA0_CSR		(volatile u32 *)IOP3XX_REG_ADDR(0x0404)
+#define IOP3XX_DMA0_DAR		(volatile u32 *)IOP3XX_REG_ADDR(0x040c)
+#define IOP3XX_DMA0_NDAR	(volatile u32 *)IOP3XX_REG_ADDR(0x0410)
+#define IOP3XX_DMA0_PADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0414)
+#define IOP3XX_DMA0_PUADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0418)
+#define IOP3XX_DMA0_LADR	(volatile u32 *)IOP3XX_REG_ADDR(0x041c)
+#define IOP3XX_DMA0_BCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0420)
+#define IOP3XX_DMA0_DCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0424)
+#define IOP3XX_DMA1_CCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0440)
+#define IOP3XX_DMA1_CSR		(volatile u32 *)IOP3XX_REG_ADDR(0x0444)
+#define IOP3XX_DMA1_DAR		(volatile u32 *)IOP3XX_REG_ADDR(0x044c)
+#define IOP3XX_DMA1_NDAR	(volatile u32 *)IOP3XX_REG_ADDR(0x0450)
+#define IOP3XX_DMA1_PADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0454)
+#define IOP3XX_DMA1_PUADR	(volatile u32 *)IOP3XX_REG_ADDR(0x0458)
+#define IOP3XX_DMA1_LADR	(volatile u32 *)IOP3XX_REG_ADDR(0x045c)
+#define IOP3XX_DMA1_BCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0460)
+#define IOP3XX_DMA1_DCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0464)
+
+/* Peripheral bus interface  */
+#define IOP3XX_PBCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0680)
+#define IOP3XX_PBISR		(volatile u32 *)IOP3XX_REG_ADDR(0x0684)
+#define IOP3XX_PBBAR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0688)
+#define IOP3XX_PBLR0		(volatile u32 *)IOP3XX_REG_ADDR(0x068c)
+#define IOP3XX_PBBAR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0690)
+#define IOP3XX_PBLR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0694)
+#define IOP3XX_PBBAR2		(volatile u32 *)IOP3XX_REG_ADDR(0x0698)
+#define IOP3XX_PBLR2		(volatile u32 *)IOP3XX_REG_ADDR(0x069c)
+#define IOP3XX_PBBAR3		(volatile u32 *)IOP3XX_REG_ADDR(0x06a0)
+#define IOP3XX_PBLR3		(volatile u32 *)IOP3XX_REG_ADDR(0x06a4)
+#define IOP3XX_PBBAR4		(volatile u32 *)IOP3XX_REG_ADDR(0x06a8)
+#define IOP3XX_PBLR4		(volatile u32 *)IOP3XX_REG_ADDR(0x06ac)
+#define IOP3XX_PBBAR5		(volatile u32 *)IOP3XX_REG_ADDR(0x06b0)
+#define IOP3XX_PBLR5		(volatile u32 *)IOP3XX_REG_ADDR(0x06b4)
+#define IOP3XX_PMBR0		(volatile u32 *)IOP3XX_REG_ADDR(0x06c0)
+#define IOP3XX_PMBR1		(volatile u32 *)IOP3XX_REG_ADDR(0x06e0)
+#define IOP3XX_PMBR2		(volatile u32 *)IOP3XX_REG_ADDR(0x06e4)
+
+/* Peripheral performance monitoring unit  */
+#define IOP3XX_GTMR		(volatile u32 *)IOP3XX_REG_ADDR(0x0700)
+#define IOP3XX_ESR		(volatile u32 *)IOP3XX_REG_ADDR(0x0704)
+#define IOP3XX_EMISR		(volatile u32 *)IOP3XX_REG_ADDR(0x0708)
+#define IOP3XX_GTSR		(volatile u32 *)IOP3XX_REG_ADDR(0x0710)
+/* PERCR0 DOESN'T EXIST - index from 1! */
+#define IOP3XX_PERCR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0710)
+
+/* General Purpose I/O  */
+#define IOP3XX_GPOE		(volatile u32 *)IOP3XX_GPIO_REG(0x0004)
+#define IOP3XX_GPID		(volatile u32 *)IOP3XX_GPIO_REG(0x0008)
+#define IOP3XX_GPOD		(volatile u32 *)IOP3XX_GPIO_REG(0x000c)
+
+/* Timers  */
+#define IOP3XX_TU_TMR0		(volatile u32 *)IOP3XX_TIMER_REG(0x0000)
+#define IOP3XX_TU_TMR1		(volatile u32 *)IOP3XX_TIMER_REG(0x0004)
+#define IOP3XX_TU_TCR0		(volatile u32 *)IOP3XX_TIMER_REG(0x0008)
+#define IOP3XX_TU_TCR1		(volatile u32 *)IOP3XX_TIMER_REG(0x000c)
+#define IOP3XX_TU_TRR0		(volatile u32 *)IOP3XX_TIMER_REG(0x0010)
+#define IOP3XX_TU_TRR1		(volatile u32 *)IOP3XX_TIMER_REG(0x0014)
+#define IOP3XX_TU_TISR		(volatile u32 *)IOP3XX_TIMER_REG(0x0018)
+#define IOP3XX_TU_WDTCR		(volatile u32 *)IOP3XX_TIMER_REG(0x001c)
+#define IOP3XX_TMR_TC		0x01
+#define IOP3XX_TMR_EN		0x02
+#define IOP3XX_TMR_RELOAD	0x04
+#define IOP3XX_TMR_PRIVILEGED	0x09
+#define IOP3XX_TMR_RATIO_1_1	0x00
+#define IOP3XX_TMR_RATIO_4_1	0x10
+#define IOP3XX_TMR_RATIO_8_1	0x20
+#define IOP3XX_TMR_RATIO_16_1	0x30
+
+/* Application accelerator unit  */
+#define IOP3XX_AAU_ACR		(volatile u32 *)IOP3XX_REG_ADDR(0x0800)
+#define IOP3XX_AAU_ASR		(volatile u32 *)IOP3XX_REG_ADDR(0x0804)
+#define IOP3XX_AAU_ADAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0808)
+#define IOP3XX_AAU_ANDAR	(volatile u32 *)IOP3XX_REG_ADDR(0x080c)
+#define IOP3XX_AAU_SAR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0810)
+#define IOP3XX_AAU_SAR2		(volatile u32 *)IOP3XX_REG_ADDR(0x0814)
+#define IOP3XX_AAU_SAR3		(volatile u32 *)IOP3XX_REG_ADDR(0x0818)
+#define IOP3XX_AAU_SAR4		(volatile u32 *)IOP3XX_REG_ADDR(0x081c)
+#define IOP3XX_AAU_DAR		(volatile u32 *)IOP3XX_REG_ADDR(0x0820)
+#define IOP3XX_AAU_ABCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0824)
+#define IOP3XX_AAU_ADCR		(volatile u32 *)IOP3XX_REG_ADDR(0x0828)
+#define IOP3XX_AAU_SAR5		(volatile u32 *)IOP3XX_REG_ADDR(0x082c)
+#define IOP3XX_AAU_SAR6		(volatile u32 *)IOP3XX_REG_ADDR(0x0830)
+#define IOP3XX_AAU_SAR7		(volatile u32 *)IOP3XX_REG_ADDR(0x0834)
+#define IOP3XX_AAU_SAR8		(volatile u32 *)IOP3XX_REG_ADDR(0x0838)
+#define IOP3XX_AAU_EDCR0	(volatile u32 *)IOP3XX_REG_ADDR(0x083c)
+#define IOP3XX_AAU_SAR9		(volatile u32 *)IOP3XX_REG_ADDR(0x0840)
+#define IOP3XX_AAU_SAR10	(volatile u32 *)IOP3XX_REG_ADDR(0x0844)
+#define IOP3XX_AAU_SAR11	(volatile u32 *)IOP3XX_REG_ADDR(0x0848)
+#define IOP3XX_AAU_SAR12	(volatile u32 *)IOP3XX_REG_ADDR(0x084c)
+#define IOP3XX_AAU_SAR13	(volatile u32 *)IOP3XX_REG_ADDR(0x0850)
+#define IOP3XX_AAU_SAR14	(volatile u32 *)IOP3XX_REG_ADDR(0x0854)
+#define IOP3XX_AAU_SAR15	(volatile u32 *)IOP3XX_REG_ADDR(0x0858)
+#define IOP3XX_AAU_SAR16	(volatile u32 *)IOP3XX_REG_ADDR(0x085c)
+#define IOP3XX_AAU_EDCR1	(volatile u32 *)IOP3XX_REG_ADDR(0x0860)
+#define IOP3XX_AAU_SAR17	(volatile u32 *)IOP3XX_REG_ADDR(0x0864)
+#define IOP3XX_AAU_SAR18	(volatile u32 *)IOP3XX_REG_ADDR(0x0868)
+#define IOP3XX_AAU_SAR19	(volatile u32 *)IOP3XX_REG_ADDR(0x086c)
+#define IOP3XX_AAU_SAR20	(volatile u32 *)IOP3XX_REG_ADDR(0x0870)
+#define IOP3XX_AAU_SAR21	(volatile u32 *)IOP3XX_REG_ADDR(0x0874)
+#define IOP3XX_AAU_SAR22	(volatile u32 *)IOP3XX_REG_ADDR(0x0878)
+#define IOP3XX_AAU_SAR23	(volatile u32 *)IOP3XX_REG_ADDR(0x087c)
+#define IOP3XX_AAU_SAR24	(volatile u32 *)IOP3XX_REG_ADDR(0x0880)
+#define IOP3XX_AAU_EDCR2	(volatile u32 *)IOP3XX_REG_ADDR(0x0884)
+#define IOP3XX_AAU_SAR25	(volatile u32 *)IOP3XX_REG_ADDR(0x0888)
+#define IOP3XX_AAU_SAR26	(volatile u32 *)IOP3XX_REG_ADDR(0x088c)
+#define IOP3XX_AAU_SAR27	(volatile u32 *)IOP3XX_REG_ADDR(0x0890)
+#define IOP3XX_AAU_SAR28	(volatile u32 *)IOP3XX_REG_ADDR(0x0894)
+#define IOP3XX_AAU_SAR29	(volatile u32 *)IOP3XX_REG_ADDR(0x0898)
+#define IOP3XX_AAU_SAR30	(volatile u32 *)IOP3XX_REG_ADDR(0x089c)
+#define IOP3XX_AAU_SAR31	(volatile u32 *)IOP3XX_REG_ADDR(0x08a0)
+#define IOP3XX_AAU_SAR32	(volatile u32 *)IOP3XX_REG_ADDR(0x08a4)
+
+/* I2C bus interface unit  */
+#define IOP3XX_ICR0		(volatile u32 *)IOP3XX_REG_ADDR(0x1680)
+#define IOP3XX_ISR0		(volatile u32 *)IOP3XX_REG_ADDR(0x1684)
+#define IOP3XX_ISAR0		(volatile u32 *)IOP3XX_REG_ADDR(0x1688)
+#define IOP3XX_IDBR0		(volatile u32 *)IOP3XX_REG_ADDR(0x168c)
+#define IOP3XX_IBMR0		(volatile u32 *)IOP3XX_REG_ADDR(0x1694)
+#define IOP3XX_ICR1		(volatile u32 *)IOP3XX_REG_ADDR(0x16a0)
+#define IOP3XX_ISR1		(volatile u32 *)IOP3XX_REG_ADDR(0x16a4)
+#define IOP3XX_ISAR1		(volatile u32 *)IOP3XX_REG_ADDR(0x16a8)
+#define IOP3XX_IDBR1		(volatile u32 *)IOP3XX_REG_ADDR(0x16ac)
+#define IOP3XX_IBMR1		(volatile u32 *)IOP3XX_REG_ADDR(0x16b4)
+
+
+/*
+ * IOP3XX I/O and Mem space regions for PCI autoconfiguration
+ */
+#define IOP3XX_PCI_MEM_WINDOW_SIZE	0x04000000
+#define IOP3XX_PCI_LOWER_MEM_PA		0x80000000
+#define IOP3XX_PCI_LOWER_MEM_BA		(*IOP3XX_OMWTVR0)
+
+#define IOP3XX_PCI_IO_WINDOW_SIZE	0x00010000
+#define IOP3XX_PCI_LOWER_IO_PA		0x90000000
+#define IOP3XX_PCI_LOWER_IO_VA		0xfe000000
+#define IOP3XX_PCI_LOWER_IO_BA		(*IOP3XX_OIOWTVR)
+
+
+#ifndef __ASSEMBLY__
+void iop3xx_map_io(void);
+void iop3xx_init_time(unsigned long);
+unsigned long iop3xx_gettimeoffset(void);
+
+extern struct platform_device iop3xx_i2c0_device;
+extern struct platform_device iop3xx_i2c1_device;
+
+extern inline void iop3xx_cp6_enable(void)
+{
+	u32 temp;
+
+	asm volatile (
+		"mrc	p15, 0, %0, c15, c1, 0\n\t"
+		"orr	%0, %0, #(1 << 6)\n\t"
+		"mcr	p15, 0, %0, c15, c1, 0\n\t"
+		"mrc	p15, 0, %0, c15, c1, 0\n\t"
+		"mov	%0, %0\n\t"
+		"sub	pc, pc, #4\n\t"
+		: "=r" (temp) );
+}
+
+extern inline void iop3xx_cp6_disable(void)
+{
+	u32 temp;
+
+	asm volatile (
+		"mrc	p15, 0, %0, c15, c1, 0\n\t"
+		"bic	%0, %0, #(1 << 6)\n\t"
+		"mcr	p15, 0, %0, c15, c1, 0\n\t"
+		"mrc	p15, 0, %0, c15, c1, 0\n\t"
+		"mov	%0, %0\n\t"
+		"sub	pc, pc, #4\n\t"
+		: "=r" (temp) );
+}
+#endif
+
+
+#endif
diff --git a/include/asm-arm/hardware/locomo.h b/include/asm-arm/hardware/locomo.h
index 22dfb17..adab777 100644
--- a/include/asm-arm/hardware/locomo.h
+++ b/include/asm-arm/hardware/locomo.h
@@ -54,17 +54,18 @@
 #define	LOCOMO_DAC_SDAOEB	0x01	/* SDA pin output data       */
 
 /* SPI interface */
-#define LOCOMO_SPIMD	0x60		/* SPI mode setting */
-#define LOCOMO_SPICT	0x64		/* SPI mode control */
-#define LOCOMO_SPIST	0x68		/* SPI status */
-#define LOCOMO_SPIIS	0x70		/* SPI interrupt status */
-#define LOCOMO_SPIWE	0x74		/* SPI interrupt status write enable */
-#define LOCOMO_SPIIE	0x78		/* SPI interrupt enable */
-#define LOCOMO_SPIIR	0x7c		/* SPI interrupt request */
-#define LOCOMO_SPITD	0x80		/* SPI transfer data write */
-#define LOCOMO_SPIRD	0x84		/* SPI receive data read */
-#define LOCOMO_SPITS	0x88		/* SPI transfer data shift */
-#define LOCOMO_SPIRS	0x8C		/* SPI receive data shift */
+#define LOCOMO_SPI	0x60
+#define LOCOMO_SPIMD	0x00		/* SPI mode setting */
+#define LOCOMO_SPICT	0x04		/* SPI mode control */
+#define LOCOMO_SPIST	0x08		/* SPI status */
+#define LOCOMO_SPIIS	0x10		/* SPI interrupt status */
+#define LOCOMO_SPIWE	0x14		/* SPI interrupt status write enable */
+#define LOCOMO_SPIIE	0x18		/* SPI interrupt enable */
+#define LOCOMO_SPIIR	0x1c		/* SPI interrupt request */
+#define LOCOMO_SPITD	0x20		/* SPI transfer data write */
+#define LOCOMO_SPIRD	0x24		/* SPI receive data read */
+#define LOCOMO_SPITS	0x28		/* SPI transfer data shift */
+#define LOCOMO_SPIRS	0x2C		/* SPI receive data shift */
 #define	LOCOMO_SPI_TEND	(1 << 3)	/* Transfer end bit */
 #define	LOCOMO_SPI_OVRN	(1 << 2)	/* Over Run bit */
 #define	LOCOMO_SPI_RFW	(1 << 1)	/* write buffer bit */
@@ -161,6 +162,7 @@
 #define LOCOMO_DEVID_AUDIO	3
 #define LOCOMO_DEVID_LED	4
 #define LOCOMO_DEVID_UART	5
+#define LOCOMO_DEVID_SPI		6
 
 struct locomo_dev {
 	struct device	dev;
@@ -197,10 +199,11 @@
 void locomo_driver_unregister(struct locomo_driver *);
 
 /* GPIO control functions */
-void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir);
-unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits);
-unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits);
-void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set);
+void locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir);
+int locomo_gpio_read_level(struct device *dev, unsigned int bits);
+int locomo_gpio_read_output(struct device *dev, unsigned int bits);
+void locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set);
+
 
 /* M62332 control function */
 void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel);
diff --git a/include/asm-arm/hardware/sharpsl_pm.h b/include/asm-arm/hardware/sharpsl_pm.h
index ecf15b8..a836e76 100644
--- a/include/asm-arm/hardware/sharpsl_pm.h
+++ b/include/asm-arm/hardware/sharpsl_pm.h
@@ -25,6 +25,7 @@
 	void (*measure_temp)(int);
 	void (*presuspend)(void);
 	void (*postsuspend)(void);
+	void (*earlyresume)(void);
 	unsigned long (*read_devdata)(int);
 #define SHARPSL_BATT_VOLT       1
 #define SHARPSL_BATT_TEMP       2
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index bf7b9de..8076a85 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -280,6 +280,10 @@
 #define BIOVEC_MERGEABLE(vec1, vec2)	\
 	((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(unsigned long addr, size_t size);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
diff --git a/include/asm-arm/irqflags.h b/include/asm-arm/irqflags.h
new file mode 100644
index 0000000..6d09974
--- /dev/null
+++ b/include/asm-arm/irqflags.h
@@ -0,0 +1,132 @@
+#ifndef __ASM_ARM_IRQFLAGS_H
+#define __ASM_ARM_IRQFLAGS_H
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+
+/*
+ * CPU interrupt mask handling.
+ */
+#if __LINUX_ARM_ARCH__ >= 6
+
+#define raw_local_irq_save(x)					\
+	({							\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_irq_save\n"	\
+	"cpsid	i"						\
+	: "=r" (x) : : "memory", "cc");				\
+	})
+
+#define raw_local_irq_enable()  __asm__("cpsie i	@ __sti" : : : "memory", "cc")
+#define raw_local_irq_disable() __asm__("cpsid i	@ __cli" : : : "memory", "cc")
+#define local_fiq_enable()  __asm__("cpsie f	@ __stf" : : : "memory", "cc")
+#define local_fiq_disable() __asm__("cpsid f	@ __clf" : : : "memory", "cc")
+
+#else
+
+/*
+ * Save the current interrupt enable state & disable IRQs
+ */
+#define raw_local_irq_save(x)					\
+	({							\
+		unsigned long temp;				\
+		(void) (&temp == &x);				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_irq_save\n"	\
+"	orr	%1, %0, #128\n"					\
+"	msr	cpsr_c, %1"					\
+	: "=r" (x), "=r" (temp)					\
+	:							\
+	: "memory", "cc");					\
+	})
+	
+/*
+ * Enable IRQs
+ */
+#define raw_local_irq_enable()					\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_irq_enable\n"	\
+"	bic	%0, %0, #128\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory", "cc");					\
+	})
+
+/*
+ * Disable IRQs
+ */
+#define raw_local_irq_disable()					\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_irq_disable\n"	\
+"	orr	%0, %0, #128\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory", "cc");					\
+	})
+
+/*
+ * Enable FIQs
+ */
+#define local_fiq_enable()					\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ stf\n"		\
+"	bic	%0, %0, #64\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory", "cc");					\
+	})
+
+/*
+ * Disable FIQs
+ */
+#define local_fiq_disable()					\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ clf\n"		\
+"	orr	%0, %0, #64\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory", "cc");					\
+	})
+
+#endif
+
+/*
+ * Save the current interrupt enable state.
+ */
+#define raw_local_save_flags(x)					\
+	({							\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_save_flags"	\
+	: "=r" (x) : : "memory", "cc");				\
+	})
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+#define raw_local_irq_restore(x)				\
+	__asm__ __volatile__(					\
+	"msr	cpsr_c, %0		@ local_irq_restore\n"	\
+	:							\
+	: "r" (x)						\
+	: "memory", "cc")
+
+#define raw_irqs_disabled_flags(flags)	\
+({					\
+	(int)((flags) & PSR_I_BIT);	\
+})
+
+#endif
+#endif
diff --git a/include/asm-arm/mach/pci.h b/include/asm-arm/mach/pci.h
index 923e0ca..24621c4 100644
--- a/include/asm-arm/mach/pci.h
+++ b/include/asm-arm/mach/pci.h
@@ -52,13 +52,9 @@
 /*
  * PCI controllers
  */
-extern int iop321_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *);
-extern void iop321_init(void);
-
-extern int iop331_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *);
-extern void iop331_init(void);
+extern int iop3xx_pci_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *);
+extern void iop3xx_pci_preinit(void);
 
 extern int dc21285_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index dee0bc3..1eb93f5 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -38,7 +38,9 @@
 	void			(*init)(void);
 	void			(*suspend)(void);
 	void			(*resume)(void);
+#ifndef CONFIG_GENERIC_TIME
 	unsigned long		(*offset)(void);
+#endif
 
 #ifdef CONFIG_NO_IDLE_HZ
 	struct dyn_tick_timer	*dyn_tick;
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 02bd3ee..7e85db7 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -174,9 +174,6 @@
 
 #endif /* STRICT_MM_TYPECHECKS */
 
-/* the upper-most page table pointer */
-extern pmd_t *top_pmd;
-
 #endif /* CONFIG_MMU */
 
 #include <asm/memory.h>
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 4d10d31..ed8cb59 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -136,6 +136,13 @@
 #define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
 
 /*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT		20
+#define SECTION_SIZE		(1UL << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+/*
  * ARMv6 supersection address mask and size definitions.
  */
 #define SUPERSECTION_SHIFT	24
diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
index 1bde92c..ea7e54c 100644
--- a/include/asm-arm/proc-fns.h
+++ b/include/asm-arm/proc-fns.h
@@ -33,6 +33,14 @@
 #   define CPU_NAME cpu_arm6
 #  endif
 # endif
+# ifdef CONFIG_CPU_ARM7TDMI
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm7tdmi
+#  endif
+# endif
 # ifdef CONFIG_CPU_ARM710
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
@@ -49,6 +57,22 @@
 #   define CPU_NAME cpu_arm720
 #  endif
 # endif
+# ifdef CONFIG_CPU_ARM740T
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm740
+#  endif
+# endif
+# ifdef CONFIG_CPU_ARM9TDMI
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm9tdmi
+#  endif
+# endif
 # ifdef CONFIG_CPU_ARM920T
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
@@ -81,6 +105,22 @@
 #   define CPU_NAME cpu_arm926
 #  endif
 # endif
+# ifdef CONFIG_CPU_ARM940T
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm940
+#  endif
+# endif
+# ifdef CONFIG_CPU_ARM946E
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm946
+#  endif
+# endif
 # ifdef CONFIG_CPU_SA110
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h
index ea3ed24..aa4b578 100644
--- a/include/asm-arm/setup.h
+++ b/include/asm-arm/setup.h
@@ -194,13 +194,15 @@
 # define NR_BANKS 8
 #endif
 
+struct membank {
+	unsigned long start;
+	unsigned long size;
+	int           node;
+};
+
 struct meminfo {
 	int nr_banks;
-	struct {
-		unsigned long start;
-		unsigned long size;
-		int           node;
-	} bank[NR_BANKS];
+	struct membank bank[NR_BANKS];
 };
 
 /*
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index 0947cbf..f05fbe3 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -46,6 +46,7 @@
 #define CPUID_TCM	2
 #define CPUID_TLBTYPE	3
 
+#ifdef CONFIG_CPU_CP15
 #define read_cpuid(reg)							\
 	({								\
 		unsigned int __val;					\
@@ -55,6 +56,9 @@
 		    : "cc");						\
 		__val;							\
 	})
+#else
+#define read_cpuid(reg) (processor_id)
+#endif
 
 /*
  * This is used to ensure the compiler did actually allocate the register we
@@ -207,130 +211,7 @@
 {
 }
 
-/*
- * CPU interrupt mask handling.
- */
-#if __LINUX_ARM_ARCH__ >= 6
-
-#define local_irq_save(x)					\
-	({							\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_save\n"	\
-	"cpsid	i"						\
-	: "=r" (x) : : "memory", "cc");				\
-	})
-
-#define local_irq_enable()  __asm__("cpsie i	@ __sti" : : : "memory", "cc")
-#define local_irq_disable() __asm__("cpsid i	@ __cli" : : : "memory", "cc")
-#define local_fiq_enable()  __asm__("cpsie f	@ __stf" : : : "memory", "cc")
-#define local_fiq_disable() __asm__("cpsid f	@ __clf" : : : "memory", "cc")
-
-#else
-
-/*
- * Save the current interrupt enable state & disable IRQs
- */
-#define local_irq_save(x)					\
-	({							\
-		unsigned long temp;				\
-		(void) (&temp == &x);				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_save\n"	\
-"	orr	%1, %0, #128\n"					\
-"	msr	cpsr_c, %1"					\
-	: "=r" (x), "=r" (temp)					\
-	:							\
-	: "memory", "cc");					\
-	})
-	
-/*
- * Enable IRQs
- */
-#define local_irq_enable()					\
-	({							\
-		unsigned long temp;				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_enable\n"	\
-"	bic	%0, %0, #128\n"					\
-"	msr	cpsr_c, %0"					\
-	: "=r" (temp)						\
-	:							\
-	: "memory", "cc");					\
-	})
-
-/*
- * Disable IRQs
- */
-#define local_irq_disable()					\
-	({							\
-		unsigned long temp;				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_irq_disable\n"	\
-"	orr	%0, %0, #128\n"					\
-"	msr	cpsr_c, %0"					\
-	: "=r" (temp)						\
-	:							\
-	: "memory", "cc");					\
-	})
-
-/*
- * Enable FIQs
- */
-#define local_fiq_enable()					\
-	({							\
-		unsigned long temp;				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ stf\n"		\
-"	bic	%0, %0, #64\n"					\
-"	msr	cpsr_c, %0"					\
-	: "=r" (temp)						\
-	:							\
-	: "memory", "cc");					\
-	})
-
-/*
- * Disable FIQs
- */
-#define local_fiq_disable()					\
-	({							\
-		unsigned long temp;				\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ clf\n"		\
-"	orr	%0, %0, #64\n"					\
-"	msr	cpsr_c, %0"					\
-	: "=r" (temp)						\
-	:							\
-	: "memory", "cc");					\
-	})
-
-#endif
-
-/*
- * Save the current interrupt enable state.
- */
-#define local_save_flags(x)					\
-	({							\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_save_flags"	\
-	: "=r" (x) : : "memory", "cc");				\
-	})
-
-/*
- * restore saved IRQ & FIQ state
- */
-#define local_irq_restore(x)					\
-	__asm__ __volatile__(					\
-	"msr	cpsr_c, %0		@ local_irq_restore\n"	\
-	:							\
-	: "r" (x)						\
-	: "memory", "cc")
-
-#define irqs_disabled()			\
-({					\
-	unsigned long flags;		\
-	local_save_flags(flags);	\
-	(int)(flags & PSR_I_BIT);	\
-})
+#include <linux/irqflags.h>
 
 #ifdef CONFIG_SMP
 
@@ -405,17 +286,17 @@
 #error SMP is not supported on this platform
 #endif
 	case 1:
-		local_irq_save(flags);
+		raw_local_irq_save(flags);
 		ret = *(volatile unsigned char *)ptr;
 		*(volatile unsigned char *)ptr = x;
-		local_irq_restore(flags);
+		raw_local_irq_restore(flags);
 		break;
 
 	case 4:
-		local_irq_save(flags);
+		raw_local_irq_save(flags);
 		ret = *(volatile unsigned long *)ptr;
 		*(volatile unsigned long *)ptr = x;
-		local_irq_restore(flags);
+		raw_local_irq_restore(flags);
 		break;
 #else
 	case 1:
diff --git a/include/asm-arm/timeofday.h b/include/asm-arm/timeofday.h
new file mode 100644
index 0000000..27254bd
--- /dev/null
+++ b/include/asm-arm/timeofday.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_ARM_TIMEOFDAY_H
+#define _ASM_ARM_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index d97fc76..cd10a0b 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -247,16 +247,16 @@
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 
 	if (tlb_flag(TLB_V3_FULL))
-		asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero));
+		asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
 	if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL))
-		asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero));
+		asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
 	if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL))
-		asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero));
+		asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
 	if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
-		asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+		asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 }
 
 static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -266,25 +266,25 @@
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 
 	if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) {
 		if (tlb_flag(TLB_V3_FULL))
-			asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero));
+			asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
 		if (tlb_flag(TLB_V4_U_FULL))
-			asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero));
+			asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
 		if (tlb_flag(TLB_V4_D_FULL))
-			asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero));
+			asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
 		if (tlb_flag(TLB_V4_I_FULL))
-			asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+			asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 	}
 
 	if (tlb_flag(TLB_V6_U_ASID))
-		asm("mcr%? p15, 0, %0, c8, c7, 2" : : "r" (asid));
+		asm("mcr p15, 0, %0, c8, c7, 2" : : "r" (asid) : "cc");
 	if (tlb_flag(TLB_V6_D_ASID))
-		asm("mcr%? p15, 0, %0, c8, c6, 2" : : "r" (asid));
+		asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
 	if (tlb_flag(TLB_V6_I_ASID))
-		asm("mcr%? p15, 0, %0, c8, c5, 2" : : "r" (asid));
+		asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
 }
 
 static inline void
@@ -296,27 +296,27 @@
 	uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero));
 
 	if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
 		if (tlb_flag(TLB_V3_PAGE))
-			asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (uaddr));
+			asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (uaddr) : "cc");
 		if (tlb_flag(TLB_V4_U_PAGE))
-			asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr));
+			asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
 		if (tlb_flag(TLB_V4_D_PAGE))
-			asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr));
+			asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
 		if (tlb_flag(TLB_V4_I_PAGE))
-			asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
+			asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
 		if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
-			asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+			asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 	}
 
 	if (tlb_flag(TLB_V6_U_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr));
+		asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
 	if (tlb_flag(TLB_V6_D_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr));
+		asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
 	if (tlb_flag(TLB_V6_I_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
+		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
 }
 
 static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -327,31 +327,31 @@
 	kaddr &= PAGE_MASK;
 
 	if (tlb_flag(TLB_WB))
-		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 
 	if (tlb_flag(TLB_V3_PAGE))
-		asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (kaddr));
+		asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
 	if (tlb_flag(TLB_V4_U_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr));
+		asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
 	if (tlb_flag(TLB_V4_D_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr));
+		asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
 	if (tlb_flag(TLB_V4_I_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr));
+		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
 	if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
-		asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+		asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 
 	if (tlb_flag(TLB_V6_U_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr));
+		asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
 	if (tlb_flag(TLB_V6_D_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr));
+		asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
 	if (tlb_flag(TLB_V6_I_PAGE))
-		asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr));
+		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
 
 	/* The ARM ARM states that the completion of a TLB maintenance
 	 * operation is only guaranteed by a DSB instruction
 	 */
 	if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE))
-		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+		asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 }
 
 /*
@@ -373,11 +373,11 @@
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_DCLEAN))
-		asm("mcr%?	p15, 0, %0, c7, c10, 1	@ flush_pmd"
-			: : "r" (pmd));
+		asm("mcr	p15, 0, %0, c7, c10, 1	@ flush_pmd"
+			: : "r" (pmd) : "cc");
 	if (tlb_flag(TLB_WB))
-		asm("mcr%?	p15, 0, %0, c7, c10, 4	@ flush_pmd"
-			: : "r" (zero));
+		asm("mcr	p15, 0, %0, c7, c10, 4	@ flush_pmd"
+			: : "r" (zero) : "cc");
 }
 
 static inline void clean_pmd_entry(pmd_t *pmd)
@@ -385,8 +385,8 @@
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_DCLEAN))
-		asm("mcr%?	p15, 0, %0, c7, c10, 1	@ flush_pmd"
-			: : "r" (pmd));
+		asm("mcr	p15, 0, %0, c7, c10, 1	@ flush_pmd"
+			: : "r" (pmd) : "cc");
 }
 
 #undef tlb_flag
diff --git a/include/asm-arm/unaligned.h b/include/asm-arm/unaligned.h
index 1b39c2f..795b9e5 100644
--- a/include/asm-arm/unaligned.h
+++ b/include/asm-arm/unaligned.h
@@ -3,7 +3,7 @@
 
 #include <asm/types.h>
 
-extern int __bug_unaligned_x(void *ptr);
+extern int __bug_unaligned_x(const void *ptr);
 
 /*
  * What is the most efficient way of loading/storing an unaligned value?
@@ -51,44 +51,32 @@
 #define __get_unaligned_4_be(__p)					\
 	(__p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3])
 
-#define __get_unaligned_le(ptr)					\
-	({							\
-		__typeof__(*(ptr)) __v;				\
-		__u8 *__p = (__u8 *)(ptr);			\
-		switch (sizeof(*(ptr))) {			\
-		case 1:	__v = *(ptr);			break;	\
-		case 2: __v = __get_unaligned_2_le(__p);	break;	\
-		case 4: __v = __get_unaligned_4_le(__p);	break;	\
-		case 8: {					\
-				unsigned int __v1, __v2;	\
-				__v2 = __get_unaligned_4_le((__p+4)); \
-				__v1 = __get_unaligned_4_le(__p);	\
-				__v = ((unsigned long long)__v2 << 32 | __v1);	\
-			}					\
-			break;					\
-		default: __v = __bug_unaligned_x(__p);	break;	\
-		}						\
-		__v;						\
+#define __get_unaligned_8_le(__p)					\
+	((unsigned long long)__get_unaligned_4_le((__p+4)) << 32 |	\
+		__get_unaligned_4_le(__p))
+
+#define __get_unaligned_8_be(__p)					\
+	((unsigned long long)__get_unaligned_4_be(__p) << 32 |		\
+		__get_unaligned_4_be((__p+4)))
+
+#define __get_unaligned_le(ptr)						\
+	({								\
+		const __u8 *__p = (const __u8 *)(ptr);			\
+		__builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,	\
+		  __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_le(__p),	\
+		  __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_le(__p),	\
+		  __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_le(__p),	\
+		    (void)__bug_unaligned_x(__p)))));			\
 	})
 
-#define __get_unaligned_be(ptr)					\
-	({							\
-		__typeof__(*(ptr)) __v;				\
-		__u8 *__p = (__u8 *)(ptr);			\
-		switch (sizeof(*(ptr))) {			\
-		case 1:	__v = *(ptr);			break;	\
-		case 2: __v = __get_unaligned_2_be(__p);	break;	\
-		case 4: __v = __get_unaligned_4_be(__p);	break;	\
-		case 8: {					\
-				unsigned int __v1, __v2;	\
-				__v2 = __get_unaligned_4_be(__p); \
-				__v1 = __get_unaligned_4_be((__p+4));	\
-				__v = ((unsigned long long)__v2 << 32 | __v1);	\
-			}					\
-			break;					\
-		default: __v = __bug_unaligned_x(__p);	break;	\
-		}						\
-		__v;						\
+#define __get_unaligned_be(ptr)						\
+	({								\
+		const __u8 *__p = (const __u8 *)(ptr);			\
+		__builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,	\
+		  __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_be(__p),	\
+		  __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_be(__p),	\
+		  __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_be(__p),	\
+		    (void)__bug_unaligned_x(__p)))));			\
 	})
 
 
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 8ceab7b..a525089 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -16,12 +16,15 @@
 #endif
 
 #ifndef HAVE_ARCH_WARN_ON
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("BUG: warning at %s:%d/%s()\n", __FILE__, __LINE__, __FUNCTION__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define WARN_ON(condition) ({						\
+	typeof(condition) __ret_warn_on = (condition);			\
+	if (unlikely(__ret_warn_on)) {					\
+		printk("BUG: warning at %s:%d/%s()\n", __FILE__,	\
+			__LINE__, __FUNCTION__);			\
+		dump_stack();						\
+	}								\
+	unlikely(__ret_warn_on);					\
+})
 #endif
 
 #else /* !CONFIG_BUG */
@@ -34,21 +37,18 @@
 #endif
 
 #ifndef HAVE_ARCH_WARN_ON
-#define WARN_ON(condition) do { if (condition) ; } while(0)
+#define WARN_ON(condition) unlikely((condition))
 #endif
 #endif
 
-#define WARN_ON_ONCE(condition)				\
-({							\
+#define WARN_ON_ONCE(condition)	({			\
 	static int __warn_once = 1;			\
-	int __ret = 0;					\
+	typeof(condition) __ret_warn_once = (condition);\
 							\
-	if (unlikely((condition) && __warn_once)) {	\
-		__warn_once = 0;			\
-		WARN_ON(1);				\
-		__ret = 1;				\
-	}						\
-	__ret;						\
+	if (likely(__warn_once))			\
+		if (WARN_ON(__ret_warn_once)) 		\
+			__warn_once = 0;		\
+	unlikely(__ret_warn_once);			\
 })
 
 #ifdef CONFIG_SMP
diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
index 576ae01..81999a3 100644
--- a/include/asm-i386/dma-mapping.h
+++ b/include/asm-i386/dma-mapping.h
@@ -21,7 +21,7 @@
 dma_map_single(struct device *dev, void *ptr, size_t size,
 	       enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
+	BUG_ON(!valid_dma_direction(direction));
 	WARN_ON(size == 0);
 	flush_write_buffers();
 	return virt_to_phys(ptr);
@@ -31,7 +31,7 @@
 dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		 enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
+	BUG_ON(!valid_dma_direction(direction));
 }
 
 static inline int
@@ -40,7 +40,7 @@
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
+	BUG_ON(!valid_dma_direction(direction));
 	WARN_ON(nents == 0 || sg[0].length == 0);
 
 	for (i = 0; i < nents; i++ ) {
@@ -57,7 +57,7 @@
 dma_map_page(struct device *dev, struct page *page, unsigned long offset,
 	     size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
+	BUG_ON(!valid_dma_direction(direction));
 	return page_to_phys(page) + offset;
 }
 
@@ -65,7 +65,7 @@
 dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
 	       enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
+	BUG_ON(!valid_dma_direction(direction));
 }
 
 
@@ -73,7 +73,7 @@
 dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 	     enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
+	BUG_ON(!valid_dma_direction(direction));
 }
 
 static inline void
diff --git a/include/asm-i386/mach-default/do_timer.h b/include/asm-i386/mach-default/do_timer.h
index 6312c3e..4182c34 100644
--- a/include/asm-i386/mach-default/do_timer.h
+++ b/include/asm-i386/mach-default/do_timer.h
@@ -16,7 +16,7 @@
 
 static inline void do_timer_interrupt_hook(struct pt_regs *regs)
 {
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode_vm(regs));
 #endif
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index a81b059..254a0fe 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -88,7 +88,7 @@
 
 static inline int apicid_to_node(int logical_apicid)
 {
-	return logical_apicid >> 5;          /* 2 clusterids per CEC */
+	return apicid_2_node[logical_apicid];
 }
 
 /* Mapping from cpu number to logical apicid */
diff --git a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h
index 95568e6..8db618c5 100644
--- a/include/asm-i386/mach-visws/do_timer.h
+++ b/include/asm-i386/mach-visws/do_timer.h
@@ -9,7 +9,7 @@
 	/* Clear the interrupt */
 	co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
 
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode_vm(regs));
 #endif
diff --git a/include/asm-i386/mach-voyager/do_timer.h b/include/asm-i386/mach-voyager/do_timer.h
index eaf5180..099fe9f 100644
--- a/include/asm-i386/mach-voyager/do_timer.h
+++ b/include/asm-i386/mach-voyager/do_timer.h
@@ -3,7 +3,7 @@
 
 static inline void do_timer_interrupt_hook(struct pt_regs *regs)
 {
-	do_timer(regs);
+	do_timer(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode_vm(regs));
 #endif
diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
index e63b6a68..4e34a46 100644
--- a/include/asm-i386/semaphore.h
+++ b/include/asm-i386/semaphore.h
@@ -126,7 +126,7 @@
 		"lea %1,%%eax\n\t"
 		"call __down_failed_interruptible\n"
 		"2:"
-		:"=a" (result), "+m" (sem->count)
+		:"=&a" (result), "+m" (sem->count)
 		:
 		:"memory");
 	return result;
@@ -148,7 +148,7 @@
 		"lea %1,%%eax\n\t"
 		"call __down_failed_trylock\n\t"
 		"2:\n"
-		:"=a" (result), "+m" (sem->count)
+		:"=&a" (result), "+m" (sem->count)
 		:
 		:"memory");
 	return result;
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 32ac8c9..915c26a 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -46,6 +46,8 @@
 
 #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);
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index f44b529..978b2c7 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -70,9 +70,10 @@
 		    "i" (__FILE__), "i" (__FUNCTION__));	\
 } while (0)
 
-#define WARN_ON(x) do {						\
-	if (__builtin_constant_p(x)) {				\
-		if (x)						\
+#define WARN_ON(x) ({						\
+	typeof(x) __ret_warn_on = (x);				\
+	if (__builtin_constant_p(__ret_warn_on)) {		\
+		if (__ret_warn_on)				\
 			__WARN();				\
 	} else {						\
 		__asm__ __volatile__(				\
@@ -80,11 +81,12 @@
 		".section __bug_table,\"a\"\n"			\
 		"\t"PPC_LONG"	1b,%1,%2,%3\n"			\
 		".previous"					\
-		: : "r" ((long)(x)),				\
+		: : "r" (__ret_warn_on),			\
 		    "i" (__LINE__ + BUG_WARNING_TRAP),		\
 		    "i" (__FILE__), "i" (__FUNCTION__));	\
 	}							\
-} while (0)
+	unlikely(__ret_warn_on);				\
+})
 
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG_ON
diff --git a/include/asm-s390/appldata.h b/include/asm-s390/appldata.h
index b177070..79283da 100644
--- a/include/asm-s390/appldata.h
+++ b/include/asm-s390/appldata.h
@@ -80,7 +80,7 @@
 	parm_list.product_id_addr = (unsigned long) id;
 	parm_list.buffer_addr = virt_to_phys(buffer);
 	asm volatile(
-		"diag %1,%0,0xdc"
+		"	diag	%1,%0,0xdc"
 		: "=d" (ry)
 		: "d" (&parm_list), "m" (parm_list), "m" (*id)
 		: "cc");
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index 399bf02..af20c74 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -30,20 +30,43 @@
 
 #ifdef __KERNEL__
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
 #define __CS_LOOP(ptr, op_val, op_string) ({				\
 	typeof(ptr->counter) old_val, new_val;				\
-        __asm__ __volatile__("   l     %0,0(%3)\n"			\
-                             "0: lr    %1,%0\n"				\
-                             op_string "  %1,%4\n"			\
-                             "   cs    %0,%1,0(%3)\n"			\
-                             "   jl    0b"				\
-                             : "=&d" (old_val), "=&d" (new_val),	\
-			       "=m" (((atomic_t *)(ptr))->counter)	\
-			     : "a" (ptr), "d" (op_val),			\
-			       "m" (((atomic_t *)(ptr))->counter)	\
-			     : "cc", "memory" );			\
+	asm volatile(							\
+		"	l	%0,%2\n"				\
+		"0:	lr	%1,%0\n"				\
+		op_string "	%1,%3\n"				\
+		"	cs	%0,%1,%2\n"				\
+		"	jl	0b"					\
+		: "=&d" (old_val), "=&d" (new_val),			\
+		  "=Q" (((atomic_t *)(ptr))->counter)			\
+		: "d" (op_val),	 "Q" (((atomic_t *)(ptr))->counter)	\
+		: "cc", "memory");					\
 	new_val;							\
 })
+
+#else /* __GNUC__ */
+
+#define __CS_LOOP(ptr, op_val, op_string) ({				\
+	typeof(ptr->counter) old_val, new_val;				\
+	asm volatile(							\
+		"	l	%0,0(%3)\n"				\
+		"0:	lr	%1,%0\n"				\
+		op_string "	%1,%4\n"				\
+		"	cs	%0,%1,0(%3)\n"				\
+		"	jl	0b"					\
+		: "=&d" (old_val), "=&d" (new_val),			\
+		  "=m" (((atomic_t *)(ptr))->counter)			\
+		: "a" (ptr), "d" (op_val),				\
+		  "m" (((atomic_t *)(ptr))->counter)			\
+		: "cc", "memory");					\
+	new_val;							\
+})
+
+#endif /* __GNUC__ */
+
 #define atomic_read(v)          ((v)->counter)
 #define atomic_set(v,i)         (((v)->counter) = (i))
 
@@ -81,10 +104,19 @@
 
 static __inline__ int atomic_cmpxchg(atomic_t *v, int old, int new)
 {
-	__asm__ __volatile__("  cs   %0,%3,0(%2)\n"
-			     : "+d" (old), "=m" (v->counter)
-			     : "a" (v), "d" (new), "m" (v->counter)
-			     : "cc", "memory" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+	asm volatile(
+		"	cs	%0,%2,%1"
+		: "+d" (old), "=Q" (v->counter)
+		: "d" (new), "Q" (v->counter)
+		: "cc", "memory");
+#else /* __GNUC__ */
+	asm volatile(
+		"	cs	%0,%3,0(%2)"
+		: "+d" (old), "=m" (v->counter)
+		: "a" (v), "d" (new), "m" (v->counter)
+		: "cc", "memory");
+#endif /* __GNUC__ */
 	return old;
 }
 
@@ -113,20 +145,43 @@
 } __attribute__ ((aligned (8))) atomic64_t;
 #define ATOMIC64_INIT(i)  { (i) }
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
 #define __CSG_LOOP(ptr, op_val, op_string) ({				\
 	typeof(ptr->counter) old_val, new_val;				\
-        __asm__ __volatile__("   lg    %0,0(%3)\n"			\
-                             "0: lgr   %1,%0\n"				\
-                             op_string "  %1,%4\n"			\
-                             "   csg   %0,%1,0(%3)\n"			\
-                             "   jl    0b"				\
-                             : "=&d" (old_val), "=&d" (new_val),	\
-			       "=m" (((atomic_t *)(ptr))->counter)	\
-			     : "a" (ptr), "d" (op_val),			\
-			       "m" (((atomic_t *)(ptr))->counter)	\
-			     : "cc", "memory" );			\
+	asm volatile(							\
+		"	lg	%0,%2\n"				\
+		"0:	lgr	%1,%0\n"				\
+		op_string "	%1,%3\n"				\
+		"	csg	%0,%1,%2\n"				\
+		"	jl	0b"					\
+		: "=&d" (old_val), "=&d" (new_val),			\
+		  "=Q" (((atomic_t *)(ptr))->counter)			\
+		: "d" (op_val),	"Q" (((atomic_t *)(ptr))->counter)	\
+		: "cc", "memory" );					\
 	new_val;							\
 })
+
+#else /* __GNUC__ */
+
+#define __CSG_LOOP(ptr, op_val, op_string) ({				\
+	typeof(ptr->counter) old_val, new_val;				\
+	asm volatile(							\
+		"	lg	%0,0(%3)\n"				\
+		"0:	lgr	%1,%0\n"				\
+		op_string "	%1,%4\n"				\
+		"	csg	%0,%1,0(%3)\n"				\
+		"	jl	0b"					\
+		: "=&d" (old_val), "=&d" (new_val),			\
+		  "=m" (((atomic_t *)(ptr))->counter)			\
+		: "a" (ptr), "d" (op_val),				\
+		  "m" (((atomic_t *)(ptr))->counter)			\
+		: "cc", "memory" );					\
+	new_val;							\
+})
+
+#endif /* __GNUC__ */
+
 #define atomic64_read(v)          ((v)->counter)
 #define atomic64_set(v,i)         (((v)->counter) = (i))
 
@@ -163,10 +218,19 @@
 static __inline__ long long atomic64_cmpxchg(atomic64_t *v,
 					     long long old, long long new)
 {
-	__asm__ __volatile__("  csg  %0,%3,0(%2)\n"
-			     : "+d" (old), "=m" (v->counter)
-			     : "a" (v), "d" (new), "m" (v->counter)
-			     : "cc", "memory" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+	asm volatile(
+		"	csg	%0,%2,%1"
+		: "+d" (old), "=Q" (v->counter)
+		: "d" (new), "Q" (v->counter)
+		: "cc", "memory");
+#else /* __GNUC__ */
+	asm volatile(
+		"	csg	%0,%3,0(%2)"
+		: "+d" (old), "=m" (v->counter)
+		: "a" (v), "d" (new), "m" (v->counter)
+		: "cc", "memory");
+#endif /* __GNUC__ */
 	return old;
 }
 
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index 0ddcdba..f79c9b7 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -67,16 +67,35 @@
 #define __BITOPS_AND		"nr"
 #define __BITOPS_XOR		"xr"
 
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)		\
-	__asm__ __volatile__("   l   %0,0(%4)\n"			\
-			     "0: lr  %1,%0\n"				\
-			     __op_string "  %1,%3\n"			\
-			     "   cs  %0,%1,0(%4)\n"			\
-			     "   jl  0b"				\
-			     : "=&d" (__old), "=&d" (__new),	       	\
-			       "=m" (*(unsigned long *) __addr)		\
-			     : "d" (__val), "a" (__addr),		\
-			       "m" (*(unsigned long *) __addr) : "cc" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\
+	asm volatile(						\
+		"	l	%0,%2\n"			\
+		"0:	lr	%1,%0\n"			\
+		__op_string "	%1,%3\n"			\
+		"	cs	%0,%1,%2\n"			\
+		"	jl	0b"				\
+		: "=&d" (__old), "=&d" (__new),			\
+		  "=Q" (*(unsigned long *) __addr)		\
+		: "d" (__val), "Q" (*(unsigned long *) __addr)	\
+		: "cc");
+
+#else /* __GNUC__ */
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\
+	asm volatile(						\
+		"	l	%0,0(%4)\n"			\
+		"0:	lr	%1,%0\n"			\
+		__op_string "	%1,%3\n"			\
+		"	cs	%0,%1,0(%4)\n"			\
+		"	jl	0b"				\
+		: "=&d" (__old), "=&d" (__new),			\
+		  "=m" (*(unsigned long *) __addr)		\
+		: "d" (__val), "a" (__addr),			\
+		  "m" (*(unsigned long *) __addr) : "cc");
+
+#endif /* __GNUC__ */
 
 #else /* __s390x__ */
 
@@ -86,21 +105,41 @@
 #define __BITOPS_AND		"ngr"
 #define __BITOPS_XOR		"xgr"
 
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)		\
-	__asm__ __volatile__("   lg  %0,0(%4)\n"			\
-			     "0: lgr %1,%0\n"				\
-			     __op_string "  %1,%3\n"			\
-			     "   csg %0,%1,0(%4)\n"			\
-			     "   jl  0b"				\
-			     : "=&d" (__old), "=&d" (__new),	       	\
-			       "=m" (*(unsigned long *) __addr)		\
-			     : "d" (__val), "a" (__addr),		\
-			       "m" (*(unsigned long *) __addr) : "cc" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\
+	asm volatile(						\
+		"	lg	%0,%2\n"			\
+		"0:	lgr	%1,%0\n"			\
+		__op_string "	%1,%3\n"			\
+		"	csg	%0,%1,%2\n"			\
+		"	jl	0b"				\
+		: "=&d" (__old), "=&d" (__new),			\
+		  "=Q" (*(unsigned long *) __addr)		\
+		: "d" (__val), "Q" (*(unsigned long *) __addr)	\
+		: "cc");
+
+#else /* __GNUC__ */
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\
+	asm volatile(						\
+		"	lg	%0,0(%4)\n"			\
+		"0:	lgr	%1,%0\n"			\
+		__op_string "	%1,%3\n"			\
+		"	csg	%0,%1,0(%4)\n"			\
+		"	jl	0b"				\
+		: "=&d" (__old), "=&d" (__new),			\
+		  "=m" (*(unsigned long *) __addr)		\
+		: "d" (__val), "a" (__addr),			\
+		  "m" (*(unsigned long *) __addr) : "cc");
+
+
+#endif /* __GNUC__ */
 
 #endif /* __s390x__ */
 
 #define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE)
-#define __BITOPS_BARRIER() __asm__ __volatile__ ( "" : : : "memory" )
+#define __BITOPS_BARRIER() asm volatile("" : : : "memory")
 
 #ifdef CONFIG_SMP
 /*
@@ -217,10 +256,10 @@
 	unsigned long addr;
 
 	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-        asm volatile("oc 0(1,%1),0(%2)"
-		     : "=m" (*(char *) addr)
-		     : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-		       "m" (*(char *) addr) : "cc" );
+	asm volatile(
+		"	oc	0(1,%1),0(%2)"
+		: "=m" (*(char *) addr) : "a" (addr),
+		  "a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
 }
 
 static inline void 
@@ -229,40 +268,7 @@
 	unsigned long addr;
 
 	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-	switch (nr&7) {
-	case 0:
-		asm volatile ("oi 0(%1),0x01" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 1:
-		asm volatile ("oi 0(%1),0x02" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 2:
-		asm volatile ("oi 0(%1),0x04" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 3:
-		asm volatile ("oi 0(%1),0x08" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 4:
-		asm volatile ("oi 0(%1),0x10" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 5:
-		asm volatile ("oi 0(%1),0x20" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 6:
-		asm volatile ("oi 0(%1),0x40" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 7:
-		asm volatile ("oi 0(%1),0x80" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	}
+	*(unsigned char *) addr |= 1 << (nr & 7);
 }
 
 #define set_bit_simple(nr,addr) \
@@ -279,10 +285,10 @@
 	unsigned long addr;
 
 	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-        asm volatile("nc 0(1,%1),0(%2)"
-		     : "=m" (*(char *) addr)
-		     : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
-		       "m" (*(char *) addr) : "cc" );
+	asm volatile(
+		"	nc	0(1,%1),0(%2)"
+		: "=m" (*(char *) addr)	: "a" (addr),
+		  "a" (_ni_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc");
 }
 
 static inline void 
@@ -291,40 +297,7 @@
 	unsigned long addr;
 
 	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-	switch (nr&7) {
-	case 0:
-		asm volatile ("ni 0(%1),0xFE" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 1:
-		asm volatile ("ni 0(%1),0xFD": "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 2:
-		asm volatile ("ni 0(%1),0xFB" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 3:
-		asm volatile ("ni 0(%1),0xF7" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 4:
-		asm volatile ("ni 0(%1),0xEF" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 5:
-		asm volatile ("ni 0(%1),0xDF" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 6:
-		asm volatile ("ni 0(%1),0xBF" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 7:
-		asm volatile ("ni 0(%1),0x7F" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	}
+	*(unsigned char *) addr &= ~(1 << (nr & 7));
 }
 
 #define clear_bit_simple(nr,addr) \
@@ -340,10 +313,10 @@
 	unsigned long addr;
 
 	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-        asm volatile("xc 0(1,%1),0(%2)"
-		     :  "=m" (*(char *) addr)
-		     : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-		       "m" (*(char *) addr) : "cc" );
+	asm volatile(
+		"	xc	0(1,%1),0(%2)"
+		:  "=m" (*(char *) addr) : "a" (addr),
+		   "a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
 }
 
 static inline void 
@@ -352,40 +325,7 @@
 	unsigned long addr;
 
 	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-	switch (nr&7) {
-	case 0:
-		asm volatile ("xi 0(%1),0x01" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 1:
-		asm volatile ("xi 0(%1),0x02" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 2:
-		asm volatile ("xi 0(%1),0x04" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 3:
-		asm volatile ("xi 0(%1),0x08" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 4:
-		asm volatile ("xi 0(%1),0x10" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 5:
-		asm volatile ("xi 0(%1),0x20" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 6:
-		asm volatile ("xi 0(%1),0x40" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	case 7:
-		asm volatile ("xi 0(%1),0x80" : "=m" (*(char *) addr)
-			      : "a" (addr), "m" (*(char *) addr) : "cc" );
-		break;
-	}
+	*(unsigned char *) addr ^= 1 << (nr & 7);
 }
 
 #define change_bit_simple(nr,addr) \
@@ -404,10 +344,11 @@
 
 	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
 	ch = *(unsigned char *) addr;
-        asm volatile("oc 0(1,%1),0(%2)"
-		     : "=m" (*(char *) addr)
-		     : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-		       "m" (*(char *) addr) : "cc", "memory" );
+	asm volatile(
+		"	oc	0(1,%1),0(%2)"
+		: "=m" (*(char *) addr)
+		: "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+		  "m" (*(char *) addr) : "cc", "memory");
 	return (ch >> (nr & 7)) & 1;
 }
 #define __test_and_set_bit(X,Y)		test_and_set_bit_simple(X,Y)
@@ -423,10 +364,11 @@
 
 	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
 	ch = *(unsigned char *) addr;
-        asm volatile("nc 0(1,%1),0(%2)"
-		     : "=m" (*(char *) addr)
-		     : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
-		       "m" (*(char *) addr) : "cc", "memory" );
+	asm volatile(
+		"	nc	0(1,%1),0(%2)"
+		: "=m" (*(char *) addr)
+		: "a" (addr), "a" (_ni_bitmap + (nr & 7)),
+		  "m" (*(char *) addr) : "cc", "memory");
 	return (ch >> (nr & 7)) & 1;
 }
 #define __test_and_clear_bit(X,Y)	test_and_clear_bit_simple(X,Y)
@@ -442,10 +384,11 @@
 
 	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
 	ch = *(unsigned char *) addr;
-        asm volatile("xc 0(1,%1),0(%2)"
-		     : "=m" (*(char *) addr)
-		     : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-		       "m" (*(char *) addr) : "cc", "memory" );
+	asm volatile(
+		"	xc	0(1,%1),0(%2)"
+		: "=m" (*(char *) addr)
+		: "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+		  "m" (*(char *) addr) : "cc", "memory");
 	return (ch >> (nr & 7)) & 1;
 }
 #define __test_and_change_bit(X,Y)	test_and_change_bit_simple(X,Y)
@@ -557,35 +500,36 @@
 
         if (!size)
                 return 0;
-        __asm__("   lhi  %1,-1\n"
-                "   lr   %2,%3\n"
-                "   slr  %0,%0\n"
-                "   ahi  %2,31\n"
-                "   srl  %2,5\n"
-                "0: c    %1,0(%0,%4)\n"
-                "   jne  1f\n"
-                "   la   %0,4(%0)\n"
-                "   brct %2,0b\n"
-                "   lr   %0,%3\n"
-                "   j    4f\n"
-                "1: l    %2,0(%0,%4)\n"
-                "   sll  %0,3\n"
-                "   lhi  %1,0xff\n"
-                "   tml  %2,0xffff\n"
-                "   jno  2f\n"
-                "   ahi  %0,16\n"
-                "   srl  %2,16\n"
-                "2: tml  %2,0x00ff\n"
-                "   jno  3f\n"
-                "   ahi  %0,8\n"
-                "   srl  %2,8\n"
-                "3: nr   %2,%1\n"
-                "   ic   %2,0(%2,%5)\n"
-                "   alr  %0,%2\n"
-                "4:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
-                : "a" (size), "a" (addr), "a" (&_zb_findmap),
-		  "m" (*(addrtype *) addr) : "cc" );
+	asm volatile(
+		"	lhi	%1,-1\n"
+		"	lr	%2,%3\n"
+		"	slr	%0,%0\n"
+		"	ahi	%2,31\n"
+		"	srl	%2,5\n"
+		"0:	c	%1,0(%0,%4)\n"
+		"	jne	1f\n"
+		"	la	%0,4(%0)\n"
+		"	brct	%2,0b\n"
+		"	lr	%0,%3\n"
+		"	j	4f\n"
+		"1:	l	%2,0(%0,%4)\n"
+		"	sll	%0,3\n"
+		"	lhi	%1,0xff\n"
+		"	tml	%2,0xffff\n"
+		"	jno	2f\n"
+		"	ahi	%0,16\n"
+		"	srl	%2,16\n"
+		"2:	tml	%2,0x00ff\n"
+		"	jno	3f\n"
+		"	ahi	%0,8\n"
+		"	srl	%2,8\n"
+		"3:	nr	%2,%1\n"
+		"	ic	%2,0(%2,%5)\n"
+		"	alr	%0,%2\n"
+		"4:"
+		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+		: "a" (size), "a" (addr), "a" (&_zb_findmap),
+		  "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -598,35 +542,36 @@
 
         if (!size)
                 return 0;
-        __asm__("   slr  %1,%1\n"
-                "   lr   %2,%3\n"
-                "   slr  %0,%0\n"
-                "   ahi  %2,31\n"
-                "   srl  %2,5\n"
-                "0: c    %1,0(%0,%4)\n"
-                "   jne  1f\n"
-                "   la   %0,4(%0)\n"
-                "   brct %2,0b\n"
-                "   lr   %0,%3\n"
-                "   j    4f\n"
-                "1: l    %2,0(%0,%4)\n"
-                "   sll  %0,3\n"
-                "   lhi  %1,0xff\n"
-                "   tml  %2,0xffff\n"
-                "   jnz  2f\n"
-                "   ahi  %0,16\n"
-                "   srl  %2,16\n"
-                "2: tml  %2,0x00ff\n"
-                "   jnz  3f\n"
-                "   ahi  %0,8\n"
-                "   srl  %2,8\n"
-                "3: nr   %2,%1\n"
-                "   ic   %2,0(%2,%5)\n"
-                "   alr  %0,%2\n"
-                "4:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
-                : "a" (size), "a" (addr), "a" (&_sb_findmap),
-		  "m" (*(addrtype *) addr) : "cc" );
+	asm volatile(
+		"	slr	%1,%1\n"
+		"	lr	%2,%3\n"
+		"	slr	%0,%0\n"
+		"	ahi	%2,31\n"
+		"	srl	%2,5\n"
+		"0:	c	%1,0(%0,%4)\n"
+		"	jne	1f\n"
+		"	la	%0,4(%0)\n"
+		"	brct	%2,0b\n"
+		"	lr	%0,%3\n"
+		"	j	4f\n"
+		"1:	l	%2,0(%0,%4)\n"
+		"	sll	%0,3\n"
+		"	lhi	%1,0xff\n"
+		"	tml	%2,0xffff\n"
+		"	jnz	2f\n"
+		"	ahi	%0,16\n"
+		"	srl	%2,16\n"
+		"2:	tml	%2,0x00ff\n"
+		"	jnz	3f\n"
+		"	ahi	%0,8\n"
+		"	srl	%2,8\n"
+		"3:	nr	%2,%1\n"
+		"	ic	%2,0(%2,%5)\n"
+		"	alr	%0,%2\n"
+		"4:"
+		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+		: "a" (size), "a" (addr), "a" (&_sb_findmap),
+		  "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -640,39 +585,40 @@
 
         if (!size)
                 return 0;
-        __asm__("   lghi  %1,-1\n"
-                "   lgr   %2,%3\n"
-                "   slgr  %0,%0\n"
-                "   aghi  %2,63\n"
-                "   srlg  %2,%2,6\n"
-                "0: cg    %1,0(%0,%4)\n"
-                "   jne   1f\n"
-                "   la    %0,8(%0)\n"
-                "   brct  %2,0b\n"
-                "   lgr   %0,%3\n"
-                "   j     5f\n"
-                "1: lg    %2,0(%0,%4)\n"
-                "   sllg  %0,%0,3\n"
-                "   clr   %2,%1\n"
-		"   jne   2f\n"
-		"   aghi  %0,32\n"
-                "   srlg  %2,%2,32\n"
-		"2: lghi  %1,0xff\n"
-                "   tmll  %2,0xffff\n"
-                "   jno   3f\n"
-                "   aghi  %0,16\n"
-                "   srl   %2,16\n"
-                "3: tmll  %2,0x00ff\n"
-                "   jno   4f\n"
-                "   aghi  %0,8\n"
-                "   srl   %2,8\n"
-                "4: ngr   %2,%1\n"
-                "   ic    %2,0(%2,%5)\n"
-                "   algr  %0,%2\n"
-                "5:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
+	asm volatile(
+		"	lghi	%1,-1\n"
+		"	lgr	%2,%3\n"
+		"	slgr	%0,%0\n"
+		"	aghi	%2,63\n"
+		"	srlg	%2,%2,6\n"
+		"0:	cg	%1,0(%0,%4)\n"
+		"	jne	1f\n"
+		"	la	%0,8(%0)\n"
+		"	brct	%2,0b\n"
+		"	lgr	%0,%3\n"
+		"	j	5f\n"
+		"1:	lg	%2,0(%0,%4)\n"
+		"	sllg	%0,%0,3\n"
+		"	clr	%2,%1\n"
+		"	jne	2f\n"
+		"	aghi	%0,32\n"
+		"	srlg	%2,%2,32\n"
+		"2:	lghi	%1,0xff\n"
+		"	tmll	%2,0xffff\n"
+		"	jno	3f\n"
+		"	aghi	%0,16\n"
+		"	srl	%2,16\n"
+		"3:	tmll	%2,0x00ff\n"
+		"	jno	4f\n"
+		"	aghi	%0,8\n"
+		"	srl	%2,8\n"
+		"4:	ngr	%2,%1\n"
+		"	ic	%2,0(%2,%5)\n"
+		"	algr	%0,%2\n"
+		"5:"
+		: "=&a" (res), "=&d" (cmp), "=&a" (count)
 		: "a" (size), "a" (addr), "a" (&_zb_findmap),
-		  "m" (*(addrtype *) addr) : "cc" );
+		  "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -684,39 +630,40 @@
 
         if (!size)
                 return 0;
-        __asm__("   slgr  %1,%1\n"
-                "   lgr   %2,%3\n"
-                "   slgr  %0,%0\n"
-                "   aghi  %2,63\n"
-                "   srlg  %2,%2,6\n"
-                "0: cg    %1,0(%0,%4)\n"
-                "   jne   1f\n"
-                "   aghi  %0,8\n"
-                "   brct  %2,0b\n"
-                "   lgr   %0,%3\n"
-                "   j     5f\n"
-                "1: lg    %2,0(%0,%4)\n"
-                "   sllg  %0,%0,3\n"
-                "   clr   %2,%1\n"
-		"   jne   2f\n"
-		"   aghi  %0,32\n"
-                "   srlg  %2,%2,32\n"
-		"2: lghi  %1,0xff\n"
-                "   tmll  %2,0xffff\n"
-                "   jnz   3f\n"
-                "   aghi  %0,16\n"
-                "   srl   %2,16\n"
-                "3: tmll  %2,0x00ff\n"
-                "   jnz   4f\n"
-                "   aghi  %0,8\n"
-                "   srl   %2,8\n"
-                "4: ngr   %2,%1\n"
-                "   ic    %2,0(%2,%5)\n"
-                "   algr  %0,%2\n"
-                "5:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
+	asm volatile(
+		"	slgr	%1,%1\n"
+		"	lgr	%2,%3\n"
+		"	slgr	%0,%0\n"
+		"	aghi	%2,63\n"
+		"	srlg	%2,%2,6\n"
+		"0:	cg	%1,0(%0,%4)\n"
+		"	jne	1f\n"
+		"	aghi	%0,8\n"
+		"	brct	%2,0b\n"
+		"	lgr	%0,%3\n"
+		"	j	5f\n"
+		"1:	lg	%2,0(%0,%4)\n"
+		"	sllg	%0,%0,3\n"
+		"	clr	%2,%1\n"
+		"	jne	2f\n"
+		"	aghi	%0,32\n"
+		"	srlg	%2,%2,32\n"
+		"2:	lghi	%1,0xff\n"
+		"	tmll	%2,0xffff\n"
+		"	jnz	3f\n"
+		"	aghi	%0,16\n"
+		"	srl	%2,16\n"
+		"3:	tmll	%2,0x00ff\n"
+		"	jnz	4f\n"
+		"	aghi	%0,8\n"
+		"	srl	%2,8\n"
+		"4:	ngr	%2,%1\n"
+		"	ic	%2,0(%2,%5)\n"
+		"	algr	%0,%2\n"
+		"5:"
+		: "=&a" (res), "=&d" (cmp), "=&a" (count)
 		: "a" (size), "a" (addr), "a" (&_sb_findmap),
-		  "m" (*(addrtype *) addr) : "cc" );
+		  "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -832,36 +779,37 @@
 
         if (!size)
                 return 0;
-        __asm__("   lhi  %1,-1\n"
-                "   lr   %2,%3\n"
-                "   ahi  %2,31\n"
-                "   srl  %2,5\n"
-                "   slr  %0,%0\n"
-                "0: cl   %1,0(%0,%4)\n"
-                "   jne  1f\n"
-                "   ahi  %0,4\n"
-                "   brct %2,0b\n"
-                "   lr   %0,%3\n"
-                "   j    4f\n"
-                "1: l    %2,0(%0,%4)\n"
-                "   sll  %0,3\n"
-                "   ahi  %0,24\n"
-                "   lhi  %1,0xff\n"
-                "   tmh  %2,0xffff\n"
-                "   jo   2f\n"
-                "   ahi  %0,-16\n"
-                "   srl  %2,16\n"
-                "2: tml  %2,0xff00\n"
-                "   jo   3f\n"
-                "   ahi  %0,-8\n"
-                "   srl  %2,8\n"
-                "3: nr   %2,%1\n"
-                "   ic   %2,0(%2,%5)\n"
-                "   alr  %0,%2\n"
-                "4:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
-                : "a" (size), "a" (vaddr), "a" (&_zb_findmap),
-		  "m" (*(addrtype *) vaddr) : "cc" );
+	asm volatile(
+		"	lhi	%1,-1\n"
+		"	lr	%2,%3\n"
+		"	ahi	%2,31\n"
+		"	srl	%2,5\n"
+		"	slr	%0,%0\n"
+		"0:	cl	%1,0(%0,%4)\n"
+		"	jne	1f\n"
+		"	ahi	%0,4\n"
+		"	brct	%2,0b\n"
+		"	lr	%0,%3\n"
+		"	j	4f\n"
+		"1:	l	%2,0(%0,%4)\n"
+		"	sll	%0,3\n"
+		"	ahi	%0,24\n"
+		"	lhi	%1,0xff\n"
+		"	tmh	%2,0xffff\n"
+		"	jo	2f\n"
+		"	ahi	%0,-16\n"
+		"	srl	%2,16\n"
+		"2:	tml	%2,0xff00\n"
+		"	jo	3f\n"
+		"	ahi	%0,-8\n"
+		"	srl	%2,8\n"
+		"3:	nr	%2,%1\n"
+		"	ic	%2,0(%2,%5)\n"
+		"	alr	%0,%2\n"
+		"4:"
+		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+		: "a" (size), "a" (vaddr), "a" (&_zb_findmap),
+		  "m" (*(addrtype *) vaddr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -875,39 +823,40 @@
 
         if (!size)
                 return 0;
-        __asm__("   lghi  %1,-1\n"
-                "   lgr   %2,%3\n"
-                "   aghi  %2,63\n"
-                "   srlg  %2,%2,6\n"
-                "   slgr  %0,%0\n"
-                "0: clg   %1,0(%0,%4)\n"
-                "   jne   1f\n"
-                "   aghi  %0,8\n"
-                "   brct  %2,0b\n"
-                "   lgr   %0,%3\n"
-                "   j     5f\n"
-                "1: cl    %1,0(%0,%4)\n"
-		"   jne   2f\n"
-		"   aghi  %0,4\n"
-		"2: l     %2,0(%0,%4)\n"
-                "   sllg  %0,%0,3\n"
-                "   aghi  %0,24\n"
-                "   lghi  %1,0xff\n"
-                "   tmlh  %2,0xffff\n"
-                "   jo    3f\n"
-                "   aghi  %0,-16\n"
-                "   srl   %2,16\n"
-                "3: tmll  %2,0xff00\n"
-                "   jo    4f\n"
-                "   aghi  %0,-8\n"
-                "   srl   %2,8\n"
-                "4: ngr   %2,%1\n"
-                "   ic    %2,0(%2,%5)\n"
-                "   algr  %0,%2\n"
-                "5:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
+	asm volatile(
+		"	lghi	%1,-1\n"
+		"	lgr	%2,%3\n"
+		"	aghi	%2,63\n"
+		"	srlg	%2,%2,6\n"
+		"	slgr	%0,%0\n"
+		"0:	clg	%1,0(%0,%4)\n"
+		"	jne	1f\n"
+		"	aghi	%0,8\n"
+		"	brct	%2,0b\n"
+		"	lgr	%0,%3\n"
+		"	j	5f\n"
+		"1:	cl	%1,0(%0,%4)\n"
+		"	jne	2f\n"
+		"	aghi	%0,4\n"
+		"2:	l	%2,0(%0,%4)\n"
+		"	sllg	%0,%0,3\n"
+		"	aghi	%0,24\n"
+		"	lghi	%1,0xff\n"
+		"	tmlh	%2,0xffff\n"
+		"	jo	3f\n"
+		"	aghi	%0,-16\n"
+		"	srl	%2,16\n"
+		"3:	tmll	%2,0xff00\n"
+		"	jo	4f\n"
+		"	aghi	%0,-8\n"
+		"	srl	%2,8\n"
+		"4:	ngr	%2,%1\n"
+		"	ic	%2,0(%2,%5)\n"
+		"	algr	%0,%2\n"
+		"5:"
+		: "=&a" (res), "=&d" (cmp), "=&a" (count)
 		: "a" (size), "a" (vaddr), "a" (&_zb_findmap),
-		  "m" (*(addrtype *) vaddr) : "cc" );
+		  "m" (*(addrtype *) vaddr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -927,13 +876,16 @@
 	p = addr + offset / __BITOPS_WORDSIZE;
         if (bit) {
 #ifndef __s390x__
-                asm("   ic   %0,0(%1)\n"
-		    "   icm  %0,2,1(%1)\n"
-		    "   icm  %0,4,2(%1)\n"
-		    "   icm  %0,8,3(%1)"
-		    : "=&a" (word) : "a" (p), "m" (*p) : "cc" );
+		asm volatile(
+			"	ic	%0,0(%1)\n"
+			"	icm	%0,2,1(%1)\n"
+			"	icm	%0,4,2(%1)\n"
+			"	icm	%0,8,3(%1)"
+			: "=&a" (word) : "a" (p), "m" (*p) : "cc");
 #else
-                asm("   lrvg %0,%1" : "=a" (word) : "m" (*p) );
+		asm volatile(
+			"	lrvg	%0,%1"
+			: "=a" (word) : "m" (*p) );
 #endif
 		/*
 		 * s390 version of ffz returns __BITOPS_WORDSIZE
diff --git a/include/asm-s390/byteorder.h b/include/asm-s390/byteorder.h
index 2cc35a0..1fe2492 100644
--- a/include/asm-s390/byteorder.h
+++ b/include/asm-s390/byteorder.h
@@ -14,60 +14,54 @@
 #ifdef __GNUC__
 
 #ifdef __s390x__
-static __inline__ __u64 ___arch__swab64p(const __u64 *x)
+static inline __u64 ___arch__swab64p(const __u64 *x)
 {
 	__u64 result;
 
-	__asm__ __volatile__ (
-		"   lrvg %0,%1"
-		: "=d" (result) : "m" (*x) );
+	asm volatile("lrvg %0,%1" : "=d" (result) : "m" (*x));
 	return result;
 }
 
-static __inline__ __u64 ___arch__swab64(__u64 x)
+static inline __u64 ___arch__swab64(__u64 x)
 {
 	__u64 result;
 
-	__asm__ __volatile__ (
-		"   lrvgr %0,%1"
-		: "=d" (result) : "d" (x) );
+	asm volatile("lrvgr %0,%1" : "=d" (result) : "d" (x));
 	return result;
 }
 
-static __inline__ void ___arch__swab64s(__u64 *x)
+static inline void ___arch__swab64s(__u64 *x)
 {
 	*x = ___arch__swab64p(x);
 }
 #endif /* __s390x__ */
 
-static __inline__ __u32 ___arch__swab32p(const __u32 *x)
+static inline __u32 ___arch__swab32p(const __u32 *x)
 {
 	__u32 result;
 	
-	__asm__ __volatile__ (
+	asm volatile(
 #ifndef __s390x__
-		"        icm   %0,8,3(%1)\n"
-		"        icm   %0,4,2(%1)\n"
-		"        icm   %0,2,1(%1)\n"
-		"        ic    %0,0(%1)"
-		: "=&d" (result) : "a" (x), "m" (*x) : "cc" );
+		"	icm	%0,8,3(%1)\n"
+		"	icm	%0,4,2(%1)\n"
+		"	icm	%0,2,1(%1)\n"
+		"	ic	%0,0(%1)"
+		: "=&d" (result) : "a" (x), "m" (*x) : "cc");
 #else /* __s390x__ */
-		"   lrv  %0,%1"
-		: "=d" (result) : "m" (*x) );
+		"	lrv	%0,%1"
+		: "=d" (result) : "m" (*x));
 #endif /* __s390x__ */
 	return result;
 }
 
-static __inline__ __u32 ___arch__swab32(__u32 x)
+static inline __u32 ___arch__swab32(__u32 x)
 {
 #ifndef __s390x__
 	return ___arch__swab32p(&x);
 #else /* __s390x__ */
 	__u32 result;
 	
-	__asm__ __volatile__ (
-		"   lrvr  %0,%1"
-		: "=d" (result) : "d" (x) );
+	asm volatile("lrvr  %0,%1" : "=d" (result) : "d" (x));
 	return result;
 #endif /* __s390x__ */
 }
@@ -81,14 +75,14 @@
 {
 	__u16 result;
 	
-	__asm__ __volatile__ (
+	asm volatile(
 #ifndef __s390x__
-		"        icm   %0,2,1(%1)\n"
-		"        ic    %0,0(%1)\n"
-		: "=&d" (result) : "a" (x), "m" (*x) : "cc" );
+		"	icm	%0,2,1(%1)\n"
+		"	ic	%0,0(%1)\n"
+		: "=&d" (result) : "a" (x), "m" (*x) : "cc");
 #else /* __s390x__ */
-		"   lrvh %0,%1"
-		: "=d" (result) : "m" (*x) );
+		"	lrvh	%0,%1"
+		: "=d" (result) : "m" (*x));
 #endif /* __s390x__ */
 	return result;
 }
diff --git a/include/asm-s390/checksum.h b/include/asm-s390/checksum.h
index 471f2af..37c362d 100644
--- a/include/asm-s390/checksum.h
+++ b/include/asm-s390/checksum.h
@@ -30,57 +30,13 @@
 static inline unsigned int
 csum_partial(const unsigned char * buff, int len, unsigned int sum)
 {
-	/*
-	 * Experiments with ethernet and slip connections show that buf
-	 * is aligned on either a 2-byte or 4-byte boundary.
-	 */
-#ifndef __s390x__
-	register_pair rp;
+	register unsigned long reg2 asm("2") = (unsigned long) buff;
+	register unsigned long reg3 asm("3") = (unsigned long) len;
 
-	rp.subreg.even = (unsigned long) buff;
-	rp.subreg.odd = (unsigned long) len;
-	__asm__ __volatile__ (
-		"0:  cksm %0,%1\n"	/* do checksum on longs */
-		"    jo   0b\n"
-		: "+&d" (sum), "+&a" (rp) : : "cc", "memory" );
-#else /* __s390x__ */
-        __asm__ __volatile__ (
-                "    lgr  2,%1\n"    /* address in gpr 2 */
-                "    lgfr 3,%2\n"    /* length in gpr 3 */
-                "0:  cksm %0,2\n"    /* do checksum on longs */
-                "    jo   0b\n"
-                : "+&d" (sum)
-                : "d" (buff), "d" (len)
-                : "cc", "memory", "2", "3" );
-#endif /* __s390x__ */
-	return sum;
-}
-
-/*
- * csum_partial as an inline function
- */
-static inline unsigned int 
-csum_partial_inline(const unsigned char * buff, int len, unsigned int sum)
-{
-#ifndef __s390x__
-	register_pair rp;
-
-	rp.subreg.even = (unsigned long) buff;
-	rp.subreg.odd = (unsigned long) len;
-	__asm__ __volatile__ (
-		"0:  cksm %0,%1\n"    /* do checksum on longs */
-		"    jo   0b\n"
-                : "+&d" (sum), "+&a" (rp) : : "cc", "memory" );
-#else /* __s390x__ */
-	__asm__ __volatile__ (
-		"    lgr  2,%1\n"    /* address in gpr 2 */
-		"    lgfr 3,%2\n"    /* length in gpr 3 */
-		"0:  cksm %0,2\n"    /* do checksum on longs */
-		"    jo   0b\n"
-                : "+&d" (sum)
-		: "d" (buff), "d" (len)
-                : "cc", "memory", "2", "3" );
-#endif /* __s390x__ */
+	asm volatile(
+		"0:	cksm	%0,%1\n"	/* do checksum on longs */
+		"	jo	0b\n"
+		: "+d" (sum), "+d" (reg2), "+d" (reg3) : : "cc", "memory");
 	return sum;
 }
 
@@ -114,7 +70,7 @@
 csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum)
 {
         memcpy(dst,src,len);
-        return csum_partial_inline(dst, len, sum);
+	return csum_partial(dst, len, sum);
 }
 
 /*
@@ -126,22 +82,22 @@
 #ifndef __s390x__
 	register_pair rp;
 
-	__asm__ __volatile__ (
-		"    slr  %N1,%N1\n" /* %0 = H L */
-		"    lr   %1,%0\n"   /* %0 = H L, %1 = H L 0 0 */
-		"    srdl %1,16\n"   /* %0 = H L, %1 = 0 H L 0 */
-		"    alr  %1,%N1\n"  /* %0 = H L, %1 = L H L 0 */
-		"    alr  %0,%1\n"   /* %0 = H+L+C L+H */
-		"    srl  %0,16\n"   /* %0 = H+L+C */
-		: "+&d" (sum), "=d" (rp) : : "cc" );
+	asm volatile(
+		"	slr	%N1,%N1\n"	/* %0 = H L */
+		"	lr	%1,%0\n"	/* %0 = H L, %1 = H L 0 0 */
+		"	srdl	%1,16\n"	/* %0 = H L, %1 = 0 H L 0 */
+		"	alr	%1,%N1\n"	/* %0 = H L, %1 = L H L 0 */
+		"	alr	%0,%1\n"	/* %0 = H+L+C L+H */
+		"	srl	%0,16\n"	/* %0 = H+L+C */
+		: "+&d" (sum), "=d" (rp) : : "cc");
 #else /* __s390x__ */
-	__asm__ __volatile__ (
-		"    sr   3,3\n"   /* %0 = H*65536 + L */
-		"    lr   2,%0\n"  /* %0 = H L, R2/R3 = H L / 0 0 */
-		"    srdl 2,16\n"  /* %0 = H L, R2/R3 = 0 H / L 0 */
-		"    alr  2,3\n"   /* %0 = H L, R2/R3 = L H / L 0 */
-		"    alr  %0,2\n"  /* %0 = H+L+C L+H */
-                "    srl  %0,16\n" /* %0 = H+L+C */
+	asm volatile(
+		"	sr	3,3\n"		/* %0 = H*65536 + L */
+		"	lr	2,%0\n"		/* %0 = H L, 2/3 = H L / 0 0 */
+		"	srdl	2,16\n"		/* %0 = H L, 2/3 = 0 H / L 0 */
+		"	alr	2,3\n"		/* %0 = H L, 2/3 = L H / L 0 */
+		"	alr	%0,2\n"		/* %0 = H+L+C L+H */
+		"	srl	%0,16\n"	/* %0 = H+L+C */
 		: "+&d" (sum) : : "cc", "2", "3");
 #endif /* __s390x__ */
 	return ((unsigned short) ~sum);
@@ -155,29 +111,7 @@
 static inline unsigned short
 ip_fast_csum(unsigned char *iph, unsigned int ihl)
 {
-	unsigned long sum;
-#ifndef __s390x__
-	register_pair rp;
-
-	rp.subreg.even = (unsigned long) iph;
-	rp.subreg.odd = (unsigned long) ihl*4;
-        __asm__ __volatile__ (
-		"    sr   %0,%0\n"   /* set sum to zero */
-                "0:  cksm %0,%1\n"   /* do checksum on longs */
-                "    jo   0b\n"
-                : "=&d" (sum), "+&a" (rp) : : "cc", "memory" );
-#else /* __s390x__ */
-        __asm__ __volatile__ (
-		"    slgr %0,%0\n"   /* set sum to zero */
-                "    lgr  2,%1\n"    /* address in gpr 2 */
-                "    lgfr 3,%2\n"    /* length in gpr 3 */
-                "0:  cksm %0,2\n"    /* do checksum on ints */
-                "    jo   0b\n"
-                : "=&d" (sum)
-                : "d" (iph), "d" (ihl*4)
-                : "cc", "memory", "2", "3" );
-#endif /* __s390x__ */
-        return csum_fold(sum);
+	return csum_fold(csum_partial(iph, ihl*4, 0));
 }
 
 /*
@@ -190,47 +124,47 @@
                    unsigned int sum)
 {
 #ifndef __s390x__
-	__asm__ __volatile__ (
-                "    alr   %0,%1\n"  /* sum += saddr */
-                "    brc   12,0f\n"
-		"    ahi   %0,1\n"   /* add carry */
+	asm volatile(
+		"	alr	%0,%1\n" /* sum += saddr */
+		"	brc	12,0f\n"
+		"	ahi	%0,1\n"  /* add carry */
 		"0:"
-		: "+&d" (sum) : "d" (saddr) : "cc" );
-	__asm__ __volatile__ (
-                "    alr   %0,%1\n"  /* sum += daddr */
-                "    brc   12,1f\n"
-                "    ahi   %0,1\n"   /* add carry */
+		: "+&d" (sum) : "d" (saddr) : "cc");
+	asm volatile(
+		"	alr	%0,%1\n" /* sum += daddr */
+		"	brc	12,1f\n"
+		"	ahi	%0,1\n"  /* add carry */
 		"1:"
-		: "+&d" (sum) : "d" (daddr) : "cc" );
-	__asm__ __volatile__ (
-                "    alr   %0,%1\n"  /* sum += (len<<16) + (proto<<8) */
-		"    brc   12,2f\n"
-		"    ahi   %0,1\n"   /* add carry */
+		: "+&d" (sum) : "d" (daddr) : "cc");
+	asm volatile(
+		"	alr	%0,%1\n" /* sum += (len<<16) + (proto<<8) */
+		"	brc	12,2f\n"
+		"	ahi	%0,1\n"  /* add carry */
 		"2:"
 		: "+&d" (sum)
 		: "d" (((unsigned int) len<<16) + (unsigned int) proto)
-		: "cc" );
+		: "cc");
 #else /* __s390x__ */
-	__asm__ __volatile__ (
-                "    lgfr  %0,%0\n"
-                "    algr  %0,%1\n"  /* sum += saddr */
-                "    brc   12,0f\n"
-		"    aghi  %0,1\n"   /* add carry */
-		"0:  algr  %0,%2\n"  /* sum += daddr */
-                "    brc   12,1f\n"
-                "    aghi  %0,1\n"   /* add carry */
-		"1:  algfr %0,%3\n"  /* sum += (len<<16) + proto */
-		"    brc   12,2f\n"
-		"    aghi  %0,1\n"   /* add carry */
-		"2:  srlg  0,%0,32\n"
-                "    alr   %0,0\n"   /* fold to 32 bits */
-                "    brc   12,3f\n"
-                "    ahi   %0,1\n"   /* add carry */
-                "3:  llgfr %0,%0"
+	asm volatile(
+		"	lgfr	%0,%0\n"
+		"	algr	%0,%1\n"  /* sum += saddr */
+		"	brc	12,0f\n"
+		"	aghi	%0,1\n"   /* add carry */
+		"0:	algr	%0,%2\n"  /* sum += daddr */
+		"	brc	12,1f\n"
+		"	aghi	%0,1\n"   /* add carry */
+		"1:	algfr	%0,%3\n"  /* sum += (len<<16) + proto */
+		"	brc	12,2f\n"
+		"	aghi	%0,1\n"   /* add carry */
+		"2:	srlg	0,%0,32\n"
+		"	alr	%0,0\n"   /* fold to 32 bits */
+		"	brc	12,3f\n"
+		"	ahi	%0,1\n"   /* add carry */
+		"3:	llgfr	%0,%0"
 		: "+&d" (sum)
 		: "d" (saddr), "d" (daddr),
 		  "d" (((unsigned int) len<<16) + (unsigned int) proto)
-		: "cc", "0" );
+		: "cc", "0");
 #endif /* __s390x__ */
 	return sum;
 }
diff --git a/include/asm-s390/div64.h b/include/asm-s390/div64.h
index af098dc..6cd978c 100644
--- a/include/asm-s390/div64.h
+++ b/include/asm-s390/div64.h
@@ -1,49 +1 @@
-#ifndef __S390_DIV64
-#define __S390_DIV64
-
-#ifndef __s390x__
-
-/* for do_div "base" needs to be smaller than 2^31-1 */
-#define do_div(n, base) ({                                      \
-	unsigned long long __n = (n);				\
-	unsigned long __r;					\
-								\
-	asm ("   slr  0,0\n"					\
-	     "   l    1,%1\n"					\
-	     "   srdl 0,1\n"					\
-	     "   dr   0,%2\n"					\
-	     "   alr  1,1\n"					\
-	     "   alr  0,0\n"					\
-	     "   lhi  2,1\n"					\
-	     "   n    2,%1\n"					\
-	     "   alr  0,2\n"					\
-	     "   clr  0,%2\n"					\
-	     "   jl   0f\n"					\
-	     "   slr  0,%2\n"					\
-             "   ahi  1,1\n"					\
-	     "0: st   1,%1\n"					\
-	     "   l    1,4+%1\n"					\
-	     "   srdl 0,1\n"					\
-             "   dr   0,%2\n"					\
-	     "   alr  1,1\n"					\
-	     "   alr  0,0\n"					\
-	     "   lhi  2,1\n"					\
-	     "   n    2,4+%1\n"					\
-	     "   alr  0,2\n"					\
-	     "   clr  0,%2\n"					\
-             "   jl   1f\n"					\
-	     "   slr  0,%2\n"					\
-	     "   ahi  1,1\n"					\
-	     "1: st   1,4+%1\n"					\
-             "   lr   %0,0"					\
-	     : "=d" (__r), "=m" (__n)				\
-	     : "d" (base), "m" (__n) : "0", "1", "2", "cc" );	\
-	(n) = (__n);						\
-        __r;                                                    \
-})
-
-#else /* __s390x__ */
 #include <asm-generic/div64.h>
-#endif /* __s390x__ */
-
-#endif
diff --git a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h
index 15fd2ed..7f6f641 100644
--- a/include/asm-s390/ebcdic.h
+++ b/include/asm-s390/ebcdic.h
@@ -26,16 +26,16 @@
 {
 	if (nr-- <= 0)
 		return;
-        __asm__ __volatile__(
-		"   bras 1,1f\n"
-		"   tr   0(1,%0),0(%2)\n"
-                "0: tr   0(256,%0),0(%2)\n"
-		"   la   %0,256(%0)\n"
-		"1: ahi  %1,-256\n"
-		"   jnm  0b\n"
-		"   ex   %1,0(1)"
-                : "+&a" (addr), "+&a" (nr)
-                : "a" (codepage) : "cc", "memory", "1" );
+	asm volatile(
+		"	bras	1,1f\n"
+		"	tr	0(1,%0),0(%2)\n"
+		"0:	tr	0(256,%0),0(%2)\n"
+		"	la	%0,256(%0)\n"
+		"1:	ahi	%1,-256\n"
+		"	jnm	0b\n"
+		"	ex	%1,0(1)"
+		: "+&a" (addr), "+&a" (nr)
+		: "a" (codepage) : "cc", "memory", "1");
 }
 
 #define ASCEBC(addr,nr) codepage_convert(_ascebc, addr, nr)
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h
index a6cc27e..63c78b9 100644
--- a/include/asm-s390/io.h
+++ b/include/asm-s390/io.h
@@ -27,18 +27,16 @@
 static inline unsigned long virt_to_phys(volatile void * address)
 {
 	unsigned long real_address;
-	__asm__ (
+	asm volatile(
 #ifndef __s390x__
-		 "   lra    %0,0(%1)\n"
-                 "   jz     0f\n"
-                 "   sr     %0,%0\n"
+		 "	lra	%0,0(%1)\n"
 #else /* __s390x__ */
-		 "   lrag   %0,0(%1)\n"
-                 "   jz     0f\n"
-                 "   slgr   %0,%0\n"
+		 "	lrag	%0,0(%1)\n"
 #endif /* __s390x__ */
+		 "	jz	0f\n"
+		 "	la	%0,0\n"
                  "0:"
-                 : "=a" (real_address) : "a" (address) : "cc" );
+		 : "=a" (real_address) : "a" (address) : "cc");
         return real_address;
 }
 
diff --git a/include/asm-s390/irq.h b/include/asm-s390/irq.h
index bd1a721..7da991a 100644
--- a/include/asm-s390/irq.h
+++ b/include/asm-s390/irq.h
@@ -19,8 +19,5 @@
 	NR_IRQS,
 };
 
-#define touch_nmi_watchdog() do { } while(0)
-
 #endif /* __KERNEL__ */
 #endif
-
diff --git a/include/asm-s390/irqflags.h b/include/asm-s390/irqflags.h
index 3b566a5..3f26131 100644
--- a/include/asm-s390/irqflags.h
+++ b/include/asm-s390/irqflags.h
@@ -10,43 +10,93 @@
 
 #ifdef __KERNEL__
 
-/* interrupt control.. */
-#define raw_local_irq_enable() ({ \
-	unsigned long  __dummy; \
-	__asm__ __volatile__ ( \
-		"stosm 0(%1),0x03" \
-		: "=m" (__dummy) : "a" (&__dummy) : "memory" ); \
-	})
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
 
-#define raw_local_irq_disable() ({ \
-	unsigned long __flags; \
-	__asm__ __volatile__ ( \
-		"stnsm 0(%1),0xfc" : "=m" (__flags) : "a" (&__flags) ); \
-	__flags; \
-	})
-
-#define raw_local_save_flags(x)							\
-do {										\
-	typecheck(unsigned long, x);						\
-	__asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x), "m" (x) );	\
-} while (0)
-
-#define raw_local_irq_restore(x)						\
-do {										\
-	typecheck(unsigned long, x);						\
-	__asm__ __volatile__("ssm   0(%0)" : : "a" (&x), "m" (x) : "memory");	\
-} while (0)
-
-#define raw_irqs_disabled()		\
-({					\
-	unsigned long flags;		\
-	raw_local_save_flags(flags);	\
-	!((flags >> __FLAG_SHIFT) & 3);	\
+/* store then or system mask. */
+#define __raw_local_irq_stosm(__or)					\
+({									\
+	unsigned long __mask;						\
+	asm volatile(							\
+		"	stosm	%0,%1"					\
+		: "=Q" (__mask) : "i" (__or) : "memory");		\
+	__mask;								\
 })
 
+/* store then and system mask. */
+#define __raw_local_irq_stnsm(__and)					\
+({									\
+	unsigned long __mask;						\
+	asm volatile(							\
+		"	stnsm	%0,%1"					\
+		: "=Q" (__mask) : "i" (__and) : "memory");		\
+	__mask;								\
+})
+
+/* set system mask. */
+#define __raw_local_irq_ssm(__mask)					\
+({									\
+	asm volatile("ssm   %0" : : "Q" (__mask) : "memory");		\
+})
+
+#else /* __GNUC__ */
+
+/* store then or system mask. */
+#define __raw_local_irq_stosm(__or)					\
+({									\
+	unsigned long __mask;						\
+	asm volatile(							\
+		"	stosm	0(%1),%2"				\
+		: "=m" (__mask)						\
+		: "a" (&__mask), "i" (__or) : "memory");		\
+	__mask;								\
+})
+
+/* store then and system mask. */
+#define __raw_local_irq_stnsm(__and)					\
+({									\
+	unsigned long __mask;						\
+	asm volatile(							\
+		"	stnsm	0(%1),%2"				\
+		: "=m" (__mask)						\
+		: "a" (&__mask), "i" (__and) : "memory");		\
+	__mask;								\
+})
+
+/* set system mask. */
+#define __raw_local_irq_ssm(__mask)					\
+({									\
+	asm volatile(							\
+		"	ssm	0(%0)"					\
+		: : "a" (&__mask), "m" (__mask) : "memory");		\
+})
+
+#endif /* __GNUC__ */
+
+/* interrupt control.. */
+static inline unsigned long raw_local_irq_enable(void)
+{
+	return __raw_local_irq_stosm(0x03);
+}
+
+static inline unsigned long raw_local_irq_disable(void)
+{
+	return __raw_local_irq_stnsm(0xfc);
+}
+
+#define raw_local_save_flags(x)						\
+do {									\
+	typecheck(unsigned long, x);					\
+	(x) = __raw_local_irq_stosm(0x00);				\
+} while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+	__raw_local_irq_ssm(flags);
+}
+
 static inline int raw_irqs_disabled_flags(unsigned long flags)
 {
-	return !((flags >> __FLAG_SHIFT) & 3);
+	return !(flags & (3UL << (BITS_PER_LONG - 8)));
 }
 
 /* For spinlocks etc */
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index 18695d1..06583ed 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -359,7 +359,7 @@
 
 static inline void set_prefix(__u32 address)
 {
-        __asm__ __volatile__ ("spx %0" : : "m" (address) : "memory" );
+	asm volatile("spx %0" : : "m" (address) : "memory");
 }
 
 #define __PANIC_MAGIC           0xDEADC0DE
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index b2628dc..796c400 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -22,89 +22,45 @@
 #include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
-#ifndef __s390x__
-
 static inline void clear_page(void *page)
 {
-	register_pair rp;
-
-	rp.subreg.even = (unsigned long) page;
-	rp.subreg.odd = (unsigned long) 4096;
-        asm volatile ("   slr  1,1\n"
-		      "   mvcl %0,0"
-		      : "+&a" (rp) : : "memory", "cc", "1" );
+	register unsigned long reg1 asm ("1") = 0;
+	register void *reg2 asm ("2") = page;
+	register unsigned long reg3 asm ("3") = 4096;
+	asm volatile(
+		"	mvcl	2,0"
+		: "+d" (reg2), "+d" (reg3) : "d" (reg1) : "memory", "cc");
 }
 
 static inline void copy_page(void *to, void *from)
 {
-        if (MACHINE_HAS_MVPG)
-		asm volatile ("   sr   0,0\n"
-			      "   mvpg %0,%1"
-			      : : "a" ((void *)(to)), "a" ((void *)(from))
-			      : "memory", "cc", "0" );
-	else
-		asm volatile ("   mvc  0(256,%0),0(%1)\n"
-			      "   mvc  256(256,%0),256(%1)\n"
-			      "   mvc  512(256,%0),512(%1)\n"
-			      "   mvc  768(256,%0),768(%1)\n"
-			      "   mvc  1024(256,%0),1024(%1)\n"
-			      "   mvc  1280(256,%0),1280(%1)\n"
-			      "   mvc  1536(256,%0),1536(%1)\n"
-			      "   mvc  1792(256,%0),1792(%1)\n"
-			      "   mvc  2048(256,%0),2048(%1)\n"
-			      "   mvc  2304(256,%0),2304(%1)\n"
-			      "   mvc  2560(256,%0),2560(%1)\n"
-			      "   mvc  2816(256,%0),2816(%1)\n"
-			      "   mvc  3072(256,%0),3072(%1)\n"
-			      "   mvc  3328(256,%0),3328(%1)\n"
-			      "   mvc  3584(256,%0),3584(%1)\n"
-			      "   mvc  3840(256,%0),3840(%1)\n"
-			      : : "a"((void *)(to)),"a"((void *)(from)) 
-			      : "memory" );
+	if (MACHINE_HAS_MVPG) {
+		register unsigned long reg0 asm ("0") = 0;
+		asm volatile(
+			"	mvpg	%0,%1"
+			: : "a" (to), "a" (from), "d" (reg0)
+			: "memory", "cc");
+	} else
+		asm volatile(
+			"	mvc	0(256,%0),0(%1)\n"
+			"	mvc	256(256,%0),256(%1)\n"
+			"	mvc	512(256,%0),512(%1)\n"
+			"	mvc	768(256,%0),768(%1)\n"
+			"	mvc	1024(256,%0),1024(%1)\n"
+			"	mvc	1280(256,%0),1280(%1)\n"
+			"	mvc	1536(256,%0),1536(%1)\n"
+			"	mvc	1792(256,%0),1792(%1)\n"
+			"	mvc	2048(256,%0),2048(%1)\n"
+			"	mvc	2304(256,%0),2304(%1)\n"
+			"	mvc	2560(256,%0),2560(%1)\n"
+			"	mvc	2816(256,%0),2816(%1)\n"
+			"	mvc	3072(256,%0),3072(%1)\n"
+			"	mvc	3328(256,%0),3328(%1)\n"
+			"	mvc	3584(256,%0),3584(%1)\n"
+			"	mvc	3840(256,%0),3840(%1)\n"
+			: : "a" (to), "a" (from) : "memory");
 }
 
-#else /* __s390x__ */
-
-static inline void clear_page(void *page)
-{
-        asm volatile ("   lgr  2,%0\n"
-                      "   lghi 3,4096\n"
-                      "   slgr 1,1\n"
-                      "   mvcl 2,0"
-                      : : "a" ((void *) (page))
-		      : "memory", "cc", "1", "2", "3" );
-}
-
-static inline void copy_page(void *to, void *from)
-{
-        if (MACHINE_HAS_MVPG)
-		asm volatile ("   sgr  0,0\n"
-			      "   mvpg %0,%1"
-			      : : "a" ((void *)(to)), "a" ((void *)(from))
-			      : "memory", "cc", "0" );
-	else
-		asm volatile ("   mvc  0(256,%0),0(%1)\n"
-			      "   mvc  256(256,%0),256(%1)\n"
-			      "   mvc  512(256,%0),512(%1)\n"
-			      "   mvc  768(256,%0),768(%1)\n"
-			      "   mvc  1024(256,%0),1024(%1)\n"
-			      "   mvc  1280(256,%0),1280(%1)\n"
-			      "   mvc  1536(256,%0),1536(%1)\n"
-			      "   mvc  1792(256,%0),1792(%1)\n"
-			      "   mvc  2048(256,%0),2048(%1)\n"
-			      "   mvc  2304(256,%0),2304(%1)\n"
-			      "   mvc  2560(256,%0),2560(%1)\n"
-			      "   mvc  2816(256,%0),2816(%1)\n"
-			      "   mvc  3072(256,%0),3072(%1)\n"
-			      "   mvc  3328(256,%0),3328(%1)\n"
-			      "   mvc  3584(256,%0),3584(%1)\n"
-			      "   mvc  3840(256,%0),3840(%1)\n"
-			      : : "a"((void *)(to)),"a"((void *)(from)) 
-			      : "memory" );
-}
-
-#endif /* __s390x__ */
-
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
@@ -159,7 +115,7 @@
 static inline void
 page_set_storage_key(unsigned long addr, unsigned int skey)
 {
-	asm volatile ( "sske %0,%1" : : "d" (skey), "a" (addr) );
+	asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
 }
 
 static inline unsigned int
@@ -167,8 +123,7 @@
 {
 	unsigned int skey;
 
-	asm volatile ( "iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0) );
-
+	asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0));
 	return skey;
 }
 
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index e965309..ecdff13 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -31,9 +31,9 @@
  * the S390 page table tree.
  */
 #ifndef __ASSEMBLY__
+#include <linux/mm_types.h>
 #include <asm/bug.h>
 #include <asm/processor.h>
-#include <linux/threads.h>
 
 struct vm_area_struct; /* forward declaration (include/linux/mm.h) */
 struct mm_struct;
@@ -554,9 +554,10 @@
 		/* ipte in zarch mode can do the math */
 		pte_t *pto = ptep;
 #endif
-		asm volatile ("ipte %2,%3"
-			      : "=m" (*ptep) : "m" (*ptep),
-				"a" (pto), "a" (address) );
+		asm volatile(
+			"	ipte	%2,%3"
+			: "=m" (*ptep) : "m" (*ptep),
+			  "a" (pto), "a" (address));
 	}
 	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
 }
@@ -596,30 +597,31 @@
  * should therefore only be called if it is not mapped in any
  * address space.
  */
-#define page_test_and_clear_dirty(_page)				  \
-({									  \
-	struct page *__page = (_page);					  \
-	unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-	int __skey = page_get_storage_key(__physpage);			  \
-	if (__skey & _PAGE_CHANGED)					  \
-		page_set_storage_key(__physpage, __skey & ~_PAGE_CHANGED);\
-	(__skey & _PAGE_CHANGED);					  \
-})
+static inline int page_test_and_clear_dirty(struct page *page)
+{
+	unsigned long physpage = __pa((page - mem_map) << PAGE_SHIFT);
+	int skey = page_get_storage_key(physpage);
+
+	if (skey & _PAGE_CHANGED)
+		page_set_storage_key(physpage, skey & ~_PAGE_CHANGED);
+	return skey & _PAGE_CHANGED;
+}
 
 /*
  * Test and clear referenced bit in storage key.
  */
-#define page_test_and_clear_young(page)					  \
-({									  \
-	struct page *__page = (page);					  \
-	unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-	int __ccode;							  \
-	asm volatile ("rrbe 0,%1\n\t"					  \
-		      "ipm  %0\n\t"					  \
-		      "srl  %0,28\n\t" 					  \
-                      : "=d" (__ccode) : "a" (__physpage) : "cc" );	  \
-	(__ccode & 2);							  \
-})
+static inline int page_test_and_clear_young(struct page *page)
+{
+	unsigned long physpage = __pa((page - mem_map) << PAGE_SHIFT);
+	int ccode;
+
+	asm volatile (
+		"rrbe 0,%1\n"
+		"ipm  %0\n"
+		"srl  %0,28\n"
+		: "=d" (ccode) : "a" (physpage) : "cc" );
+	return ccode & 2;
+}
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
@@ -632,32 +634,28 @@
 	return __pte;
 }
 
-#define mk_pte(pg, pgprot)                                                \
-({                                                                        \
-	struct page *__page = (pg);                                       \
-	pgprot_t __pgprot = (pgprot);					  \
-	unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-	pte_t __pte = mk_pte_phys(__physpage, __pgprot);                  \
-	__pte;                                                            \
-})
+static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+	unsigned long physpage = __pa((page - mem_map) << PAGE_SHIFT);
 
-#define pfn_pte(pfn, pgprot)                                              \
-({                                                                        \
-	pgprot_t __pgprot = (pgprot);					  \
-	unsigned long __physpage = __pa((pfn) << PAGE_SHIFT);             \
-	pte_t __pte = mk_pte_phys(__physpage, __pgprot);                  \
-	__pte;                                                            \
-})
+	return mk_pte_phys(physpage, pgprot);
+}
+
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
+{
+	unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
+
+	return mk_pte_phys(physpage, pgprot);
+}
 
 #ifdef __s390x__
 
-#define pfn_pmd(pfn, pgprot)                                              \
-({                                                                        \
-	pgprot_t __pgprot = (pgprot);                                     \
-	unsigned long __physpage = __pa((pfn) << PAGE_SHIFT);             \
-	pmd_t __pmd = __pmd(__physpage + pgprot_val(__pgprot));           \
-	__pmd;                                                            \
-})
+static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
+{
+	unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
+
+	return __pmd(physpage + pgprot_val(pgprot));
+}
 
 #endif /* __s390x__ */
 
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 578c220..cbbedc6 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_S390_PROCESSOR_H
 #define __ASM_S390_PROCESSOR_H
 
-#include <asm/page.h>
 #include <asm/ptrace.h>
 
 #ifdef __KERNEL__
@@ -21,7 +20,7 @@
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
  */
-#define current_text_addr() ({ void *pc; __asm__("basr %0,0":"=a"(pc)); pc; })
+#define current_text_addr() ({ void *pc; asm("basr %0,0" : "=a" (pc)); pc; })
 
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
@@ -202,7 +201,7 @@
 static inline void cpu_relax(void)
 {
 	if (MACHINE_HAS_DIAG44)
-		asm volatile ("diag 0,0,68" : : : "memory");
+		asm volatile("diag 0,0,68" : : : "memory");
 	else
 		barrier();
 }
@@ -213,9 +212,9 @@
 static inline void __load_psw(psw_t psw)
 {
 #ifndef __s390x__
-	asm volatile ("lpsw  0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+	asm volatile("lpsw  0(%0)" : : "a" (&psw), "m" (psw) : "cc");
 #else
-	asm volatile ("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+	asm volatile("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc");
 #endif
 }
 
@@ -232,20 +231,20 @@
 	psw.mask = mask;
 
 #ifndef __s390x__
-	asm volatile (
-		"    basr %0,0\n"
-		"0:  ahi  %0,1f-0b\n"
-		"    st	  %0,4(%1)\n"
-		"    lpsw 0(%1)\n"
+	asm volatile(
+		"	basr	%0,0\n"
+		"0:	ahi	%0,1f-0b\n"
+		"	st	%0,4(%1)\n"
+		"	lpsw	0(%1)\n"
 		"1:"
-		: "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" );
+		: "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc");
 #else /* __s390x__ */
-	asm volatile (
-		"    larl  %0,1f\n"
-		"    stg   %0,8(%1)\n"
-		"    lpswe 0(%1)\n"
+	asm volatile(
+		"	larl	%0,1f\n"
+		"	stg	%0,8(%1)\n"
+		"	lpswe	0(%1)\n"
 		"1:"
-		: "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" );
+		: "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc");
 #endif /* __s390x__ */
 }
  
@@ -274,56 +273,57 @@
          * the processor is dead afterwards
          */
 #ifndef __s390x__
-        asm volatile ("    stctl 0,0,0(%2)\n"
-                      "    ni    0(%2),0xef\n" /* switch off protection */
-                      "    lctl  0,0,0(%2)\n"
-                      "    stpt  0xd8\n"       /* store timer */
-                      "    stckc 0xe0\n"       /* store clock comparator */
-                      "    stpx  0x108\n"      /* store prefix register */
-                      "    stam  0,15,0x120\n" /* store access registers */
-                      "    std   0,0x160\n"    /* store f0 */
-                      "    std   2,0x168\n"    /* store f2 */
-                      "    std   4,0x170\n"    /* store f4 */
-                      "    std   6,0x178\n"    /* store f6 */
-                      "    stm   0,15,0x180\n" /* store general registers */
-                      "    stctl 0,15,0x1c0\n" /* store control registers */
-                      "    oi    0x1c0,0x10\n" /* fake protection bit */
-                      "    lpsw 0(%1)"
-                      : "=m" (ctl_buf)
-		      : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
+	asm volatile(
+		"	stctl	0,0,0(%2)\n"
+		"	ni	0(%2),0xef\n"	/* switch off protection */
+		"	lctl	0,0,0(%2)\n"
+		"	stpt	0xd8\n"		/* store timer */
+		"	stckc	0xe0\n"		/* store clock comparator */
+		"	stpx	0x108\n"	/* store prefix register */
+		"	stam	0,15,0x120\n"	/* store access registers */
+		"	std	0,0x160\n"	/* store f0 */
+		"	std	2,0x168\n"	/* store f2 */
+		"	std	4,0x170\n"	/* store f4 */
+		"	std	6,0x178\n"	/* store f6 */
+		"	stm	0,15,0x180\n"	/* store general registers */
+		"	stctl	0,15,0x1c0\n"	/* store control registers */
+		"	oi	0x1c0,0x10\n"	/* fake protection bit */
+		"	lpsw	0(%1)"
+		: "=m" (ctl_buf)
+		: "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc");
 #else /* __s390x__ */
-        asm volatile ("    stctg 0,0,0(%2)\n"
-                      "    ni    4(%2),0xef\n" /* switch off protection */
-                      "    lctlg 0,0,0(%2)\n"
-                      "    lghi  1,0x1000\n"
-                      "    stpt  0x328(1)\n"      /* store timer */
-                      "    stckc 0x330(1)\n"      /* store clock comparator */
-                      "    stpx  0x318(1)\n"      /* store prefix register */
-                      "    stam  0,15,0x340(1)\n" /* store access registers */
-                      "    stfpc 0x31c(1)\n"      /* store fpu control */
-                      "    std   0,0x200(1)\n"    /* store f0 */
-                      "    std   1,0x208(1)\n"    /* store f1 */
-                      "    std   2,0x210(1)\n"    /* store f2 */
-                      "    std   3,0x218(1)\n"    /* store f3 */
-                      "    std   4,0x220(1)\n"    /* store f4 */
-                      "    std   5,0x228(1)\n"    /* store f5 */
-                      "    std   6,0x230(1)\n"    /* store f6 */
-                      "    std   7,0x238(1)\n"    /* store f7 */
-                      "    std   8,0x240(1)\n"    /* store f8 */
-                      "    std   9,0x248(1)\n"    /* store f9 */
-                      "    std   10,0x250(1)\n"   /* store f10 */
-                      "    std   11,0x258(1)\n"   /* store f11 */
-                      "    std   12,0x260(1)\n"   /* store f12 */
-                      "    std   13,0x268(1)\n"   /* store f13 */
-                      "    std   14,0x270(1)\n"   /* store f14 */
-                      "    std   15,0x278(1)\n"   /* store f15 */
-                      "    stmg  0,15,0x280(1)\n" /* store general registers */
-                      "    stctg 0,15,0x380(1)\n" /* store control registers */
-                      "    oi    0x384(1),0x10\n" /* fake protection bit */
-                      "    lpswe 0(%1)"
-                      : "=m" (ctl_buf)
-		      : "a" (&dw_psw), "a" (&ctl_buf),
-		        "m" (dw_psw) : "cc", "0", "1");
+	asm volatile(
+		"	stctg	0,0,0(%2)\n"
+		"	ni	4(%2),0xef\n"	/* switch off protection */
+		"	lctlg	0,0,0(%2)\n"
+		"	lghi	1,0x1000\n"
+		"	stpt	0x328(1)\n"	/* store timer */
+		"	stckc	0x330(1)\n"	/* store clock comparator */
+		"	stpx	0x318(1)\n"	/* store prefix register */
+		"	stam	0,15,0x340(1)\n"/* store access registers */
+		"	stfpc	0x31c(1)\n"	/* store fpu control */
+		"	std	0,0x200(1)\n"	/* store f0 */
+		"	std	1,0x208(1)\n"	/* store f1 */
+		"	std	2,0x210(1)\n"	/* store f2 */
+		"	std	3,0x218(1)\n"	/* store f3 */
+		"	std	4,0x220(1)\n"	/* store f4 */
+		"	std	5,0x228(1)\n"	/* store f5 */
+		"	std	6,0x230(1)\n"	/* store f6 */
+		"	std	7,0x238(1)\n"	/* store f7 */
+		"	std	8,0x240(1)\n"	/* store f8 */
+		"	std	9,0x248(1)\n"	/* store f9 */
+		"	std	10,0x250(1)\n"	/* store f10 */
+		"	std	11,0x258(1)\n"	/* store f11 */
+		"	std	12,0x260(1)\n"	/* store f12 */
+		"	std	13,0x268(1)\n"	/* store f13 */
+		"	std	14,0x270(1)\n"	/* store f14 */
+		"	std	15,0x278(1)\n"	/* store f15 */
+		"	stmg	0,15,0x280(1)\n"/* store general registers */
+		"	stctg	0,15,0x380(1)\n"/* store control registers */
+		"	oi	0x384(1),0x10\n"/* fake protection bit */
+		"	lpswe	0(%1)"
+		: "=m" (ctl_buf)
+		: "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0");
 #endif /* __s390x__ */
 }
 
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 4d75d77..8d2bf65 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -479,7 +479,7 @@
 static inline void
 psw_set_key(unsigned int key)
 {
-	asm volatile ( "spka 0(%0)" : : "d" (key) );
+	asm volatile("spka 0(%0)" : : "d" (key));
 }
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-s390/rwsem.h b/include/asm-s390/rwsem.h
index 13ec169..90f4ecc 100644
--- a/include/asm-s390/rwsem.h
+++ b/include/asm-s390/rwsem.h
@@ -122,23 +122,23 @@
 {
 	signed long old, new;
 
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: lr   %1,%0\n"
-		"   ahi  %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	l	%0,0(%3)\n"
+		"0:	lr	%1,%0\n"
+		"	ahi	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: lgr  %1,%0\n"
-		"   aghi %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	lg	%0,0(%3)\n"
+		"0:	lgr	%1,%0\n"
+		"	aghi	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count),
-		  "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory" );
+		  "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory");
 	if (old < 0)
 		rwsem_down_read_failed(sem);
 }
@@ -150,27 +150,27 @@
 {
 	signed long old, new;
 
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: ltr  %1,%0\n"
-		"   jm   1f\n"
-		"   ahi  %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b\n"
+		"	l	%0,0(%3)\n"
+		"0:	ltr	%1,%0\n"
+		"	jm	1f\n"
+		"	ahi	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b\n"
 		"1:"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: ltgr %1,%0\n"
-		"   jm   1f\n"
-		"   aghi %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b\n"
+		"	lg	%0,0(%3)\n"
+		"0:	ltgr	%1,%0\n"
+		"	jm	1f\n"
+		"	aghi	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b\n"
 		"1:"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count),
-		  "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory" );
+		  "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory");
 	return old >= 0 ? 1 : 0;
 }
 
@@ -182,23 +182,23 @@
 	signed long old, new, tmp;
 
 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: lr   %1,%0\n"
-		"   a    %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	l	%0,0(%3)\n"
+		"0:	lr	%1,%0\n"
+		"	a	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: lgr  %1,%0\n"
-		"   ag   %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	lg	%0,0(%3)\n"
+		"0:	lgr	%1,%0\n"
+		"	ag	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count), "m" (tmp)
-		: "cc", "memory" );
+		: "cc", "memory");
 	if (old != 0)
 		rwsem_down_write_failed(sem);
 }
@@ -215,24 +215,24 @@
 {
 	signed long old;
 
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%2)\n"
-		"0: ltr  %0,%0\n"
-		"   jnz  1f\n"
-		"   cs   %0,%4,0(%2)\n"
-		"   jl   0b\n"
+		"	l	%0,0(%2)\n"
+		"0:	ltr	%0,%0\n"
+		"	jnz	1f\n"
+		"	cs	%0,%4,0(%2)\n"
+		"	jl	0b\n"
 #else /* __s390x__ */
-		"   lg   %0,0(%2)\n"
-		"0: ltgr %0,%0\n"
-		"   jnz  1f\n"
-		"   csg  %0,%4,0(%2)\n"
-		"   jl   0b\n"
+		"	lg	%0,0(%2)\n"
+		"0:	ltgr	%0,%0\n"
+		"	jnz	1f\n"
+		"	csg	%0,%4,0(%2)\n"
+		"	jl	0b\n"
 #endif /* __s390x__ */
 		"1:"
-                : "=&d" (old), "=m" (sem->count)
+		: "=&d" (old), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count),
-		  "d" (RWSEM_ACTIVE_WRITE_BIAS) : "cc", "memory" );
+		  "d" (RWSEM_ACTIVE_WRITE_BIAS) : "cc", "memory");
 	return (old == RWSEM_UNLOCKED_VALUE) ? 1 : 0;
 }
 
@@ -243,24 +243,24 @@
 {
 	signed long old, new;
 
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: lr   %1,%0\n"
-		"   ahi  %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	l	%0,0(%3)\n"
+		"0:	lr	%1,%0\n"
+		"	ahi	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: lgr  %1,%0\n"
-		"   aghi %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	lg	%0,0(%3)\n"
+		"0:	lgr	%1,%0\n"
+		"	aghi	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count),
 		  "i" (-RWSEM_ACTIVE_READ_BIAS)
-		: "cc", "memory" );
+		: "cc", "memory");
 	if (new < 0)
 		if ((new & RWSEM_ACTIVE_MASK) == 0)
 			rwsem_wake(sem);
@@ -274,23 +274,23 @@
 	signed long old, new, tmp;
 
 	tmp = -RWSEM_ACTIVE_WRITE_BIAS;
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: lr   %1,%0\n"
-		"   a    %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	l	%0,0(%3)\n"
+		"0:	lr	%1,%0\n"
+		"	a	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: lgr  %1,%0\n"
-		"   ag   %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	lg	%0,0(%3)\n"
+		"0:	lgr	%1,%0\n"
+		"	ag	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count), "m" (tmp)
-		: "cc", "memory" );
+		: "cc", "memory");
 	if (new < 0)
 		if ((new & RWSEM_ACTIVE_MASK) == 0)
 			rwsem_wake(sem);
@@ -304,23 +304,23 @@
 	signed long old, new, tmp;
 
 	tmp = -RWSEM_WAITING_BIAS;
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: lr   %1,%0\n"
-		"   a    %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	l	%0,0(%3)\n"
+		"0:	lr	%1,%0\n"
+		"	a	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: lgr  %1,%0\n"
-		"   ag   %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	lg	%0,0(%3)\n"
+		"0:	lgr	%1,%0\n"
+		"	ag	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count), "m" (tmp)
-		: "cc", "memory" );
+		: "cc", "memory");
 	if (new > 1)
 		rwsem_downgrade_wake(sem);
 }
@@ -332,23 +332,23 @@
 {
 	signed long old, new;
 
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: lr   %1,%0\n"
-		"   ar   %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	l	%0,0(%3)\n"
+		"0:	lr	%1,%0\n"
+		"	ar	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: lgr  %1,%0\n"
-		"   agr  %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	lg	%0,0(%3)\n"
+		"0:	lgr	%1,%0\n"
+		"	agr	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count), "d" (delta)
-		: "cc", "memory" );
+		: "cc", "memory");
 }
 
 /*
@@ -358,23 +358,23 @@
 {
 	signed long old, new;
 
-	__asm__ __volatile__(
+	asm volatile(
 #ifndef __s390x__
-		"   l    %0,0(%3)\n"
-		"0: lr   %1,%0\n"
-		"   ar   %1,%5\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	l	%0,0(%3)\n"
+		"0:	lr	%1,%0\n"
+		"	ar	%1,%5\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b"
 #else /* __s390x__ */
-		"   lg   %0,0(%3)\n"
-		"0: lgr  %1,%0\n"
-		"   agr  %1,%5\n"
-		"   csg  %0,%1,0(%3)\n"
-		"   jl   0b"
+		"	lg	%0,0(%3)\n"
+		"0:	lgr	%1,%0\n"
+		"	agr	%1,%5\n"
+		"	csg	%0,%1,0(%3)\n"
+		"	jl	0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+		: "=&d" (old), "=&d" (new), "=m" (sem->count)
 		: "a" (&sem->count), "m" (sem->count), "d" (delta)
-		: "cc", "memory" );
+		: "cc", "memory");
 	return new;
 }
 
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
index 32cdc69..dbce058 100644
--- a/include/asm-s390/semaphore.h
+++ b/include/asm-s390/semaphore.h
@@ -85,17 +85,17 @@
 	 *       sem->count.counter = --new_val;
 	 * In the ppc code this is called atomic_dec_if_positive.
 	 */
-	__asm__ __volatile__ (
-		"   l    %0,0(%3)\n"
-		"0: ltr  %1,%0\n"
-		"   jle  1f\n"
-		"   ahi  %1,-1\n"
-		"   cs   %0,%1,0(%3)\n"
-		"   jl   0b\n"
+	asm volatile(
+		"	l	%0,0(%3)\n"
+		"0:	ltr	%1,%0\n"
+		"	jle	1f\n"
+		"	ahi	%1,-1\n"
+		"	cs	%0,%1,0(%3)\n"
+		"	jl	0b\n"
 		"1:"
 		: "=&d" (old_val), "=&d" (new_val), "=m" (sem->count.counter)
 		: "a" (&sem->count.counter), "m" (sem->count.counter)
-		: "cc", "memory" );
+		: "cc", "memory");
 	return old_val <= 0;
 }
 
diff --git a/include/asm-s390/sfp-machine.h b/include/asm-s390/sfp-machine.h
index de69dfa..8ca8c77 100644
--- a/include/asm-s390/sfp-machine.h
+++ b/include/asm-s390/sfp-machine.h
@@ -76,21 +76,23 @@
 	unsigned int __r2 = (x2) + (y2);			\
 	unsigned int __r1 = (x1);				\
 	unsigned int __r0 = (x0);				\
-	__asm__ ("   alr %2,%3\n"				\
-		 "   brc 12,0f\n"				\
-		 "   lhi 0,1\n"					\
-		 "   alr %1,0\n"				\
-		 "   brc 12,0f\n"				\
-		 "   alr %0,0\n"				\
-		 "0:"						\
-		 : "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)	\
-		 : "d" (y0), "i" (1) : "cc", "0" );		\
-	__asm__ ("   alr %1,%2\n"				\
-		 "   brc 12,0f\n"				\
-		 "   ahi %0,1\n"				\
-		 "0:"						\
-		 : "+&d" (__r2), "+&d" (__r1)			\
-		 : "d" (y1) : "cc" );				\
+	asm volatile(						\
+		"	alr	%2,%3\n"			\
+		"	brc	12,0f\n"			\
+		"	lhi	0,1\n"				\
+		"	alr	%1,0\n"				\
+		"	brc	12,0f\n"			\
+		"	alr	%0,0\n"				\
+		"0:"						\
+		: "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)	\
+		: "d" (y0), "i" (1) : "cc", "0" );		\
+	asm volatile(						\
+		"	alr	%1,%2\n"			\
+		"	brc	12,0f\n"			\
+		"	ahi	%0,1\n"				\
+		"0:"						\
+		: "+&d" (__r2), "+&d" (__r1)			\
+		: "d" (y1) : "cc");				\
 	(r2) = __r2;						\
 	(r1) = __r1;						\
 	(r0) = __r0;						\
@@ -100,21 +102,23 @@
 	unsigned int __r2 = (x2) - (y2);			\
 	unsigned int __r1 = (x1);				\
 	unsigned int __r0 = (x0);				\
-	__asm__ ("   slr %2,%3\n"				\
-		 "   brc 3,0f\n"				\
-		 "   lhi 0,1\n"					\
-		 "   slr %1,0\n"				\
-		 "   brc 3,0f\n"				\
-		 "   slr %0,0\n"				\
-		 "0:"						\
-		 : "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)	\
-		 : "d" (y0) : "cc", "0" );			\
-	__asm__ ("   slr %1,%2\n"				\
-		 "   brc 3,0f\n"				\
-		 "   ahi %0,-1\n"				\
-		 "0:"						\
-		 : "+&d" (__r2), "+&d" (__r1)			\
-		 : "d" (y1) : "cc" );				\
+	asm volatile(						\
+		"	slr   %2,%3\n"				\
+		"	brc	3,0f\n"				\
+		"	lhi	0,1\n"				\
+		"	slr	%1,0\n"				\
+		"	brc	3,0f\n"				\
+		"	slr	%0,0\n"				\
+		"0:"						\
+		: "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)	\
+		: "d" (y0) : "cc", "0");			\
+	asm volatile(						\
+		"	slr	%1,%2\n"			\
+		"	brc	3,0f\n"				\
+		"	ahi	%0,-1\n"			\
+		"0:"						\
+		: "+&d" (__r2), "+&d" (__r1)			\
+		: "d" (y1) : "cc");				\
 	(r2) = __r2;						\
 	(r1) = __r1;						\
 	(r0) = __r0;						\
diff --git a/include/asm-s390/sigp.h b/include/asm-s390/sigp.h
index fc56458..e16d56f 100644
--- a/include/asm-s390/sigp.h
+++ b/include/asm-s390/sigp.h
@@ -70,16 +70,16 @@
 static inline sigp_ccode
 signal_processor(__u16 cpu_addr, sigp_order_code order_code)
 {
+	register unsigned long reg1 asm ("1") = 0;
 	sigp_ccode ccode;
 
-	__asm__ __volatile__(
-		"    sr     1,1\n"        /* parameter=0 in gpr 1 */
-		"    sigp   1,%1,0(%2)\n"
-		"    ipm    %0\n"
-		"    srl    %0,28\n"
-		: "=d" (ccode)
-		: "d" (__cpu_logical_map[cpu_addr]), "a" (order_code)
-		: "cc" , "memory", "1" );
+	asm volatile(
+		"	sigp	%1,%2,0(%3)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		:	"=d"	(ccode)
+		: "d" (reg1), "d" (__cpu_logical_map[cpu_addr]),
+		  "a" (order_code) : "cc" , "memory");
 	return ccode;
 }
 
@@ -87,20 +87,18 @@
  * Signal processor with parameter
  */
 static inline sigp_ccode
-signal_processor_p(__u32 parameter, __u16 cpu_addr,
-		   sigp_order_code order_code)
+signal_processor_p(__u32 parameter, __u16 cpu_addr, sigp_order_code order_code)
 {
+	register unsigned int reg1 asm ("1") = parameter;
 	sigp_ccode ccode;
-	
-	__asm__ __volatile__(
-		"    lr     1,%1\n"       /* parameter in gpr 1 */
-		"    sigp   1,%2,0(%3)\n"
-		"    ipm    %0\n"
-		"    srl    %0,28\n"
+
+	asm volatile(
+		"	sigp	%1,%2,0(%3)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
 		: "=d" (ccode)
-		: "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
-                  "a" (order_code)
-		: "cc" , "memory", "1" );
+		: "d" (reg1), "d" (__cpu_logical_map[cpu_addr]),
+		  "a" (order_code) : "cc" , "memory");
 	return ccode;
 }
 
@@ -108,24 +106,21 @@
  * Signal processor with parameter and return status
  */
 static inline sigp_ccode
-signal_processor_ps(__u32 *statusptr, __u32 parameter,
-		    __u16 cpu_addr, sigp_order_code order_code)
+signal_processor_ps(__u32 *statusptr, __u32 parameter, __u16 cpu_addr,
+		    sigp_order_code order_code)
 {
+	register unsigned int reg1 asm ("1") = parameter;
 	sigp_ccode ccode;
-	
-	__asm__ __volatile__(
-		"    sr     2,2\n"        /* clear status */
-		"    lr     3,%2\n"       /* parameter in gpr 3 */
-		"    sigp   2,%3,0(%4)\n"
-		"    st     2,%1\n"
-		"    ipm    %0\n"
-		"    srl    %0,28\n"
-		: "=d" (ccode), "=m" (*statusptr)
-		: "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
-                  "a" (order_code)
-		: "cc" , "memory", "2" , "3"
-		);
-   return ccode;
+
+	asm volatile(
+		"	sigp	%1,%2,0(%3)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28\n"
+		: "=d" (ccode), "+d" (reg1)
+		: "d" (__cpu_logical_map[cpu_addr]), "a" (order_code)
+		: "cc" , "memory");
+	*statusptr = reg1;
+	return ccode;
 }
 
 #endif /* __SIGP__ */
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index 9fb02e9..c3cf030 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -56,7 +56,7 @@
 {
         __u16 cpu_address;
  
-        __asm__ ("stap %0\n" : "=m" (cpu_address));
+	asm volatile("stap %0" : "=m" (cpu_address));
         return cpu_address;
 }
 
diff --git a/include/asm-s390/spinlock.h b/include/asm-s390/spinlock.h
index 273dbec..ce3edf6d6 100644
--- a/include/asm-s390/spinlock.h
+++ b/include/asm-s390/spinlock.h
@@ -11,17 +11,36 @@
 #ifndef __ASM_SPINLOCK_H
 #define __ASM_SPINLOCK_H
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
 static inline int
 _raw_compare_and_swap(volatile unsigned int *lock,
 		      unsigned int old, unsigned int new)
 {
-	asm volatile ("cs %0,%3,0(%4)"
-		      : "=d" (old), "=m" (*lock)
-		      : "0" (old), "d" (new), "a" (lock), "m" (*lock)
-		      : "cc", "memory" );
+	asm volatile(
+		"	cs	%0,%3,%1"
+		: "=d" (old), "=Q" (*lock)
+		: "0" (old), "d" (new), "Q" (*lock)
+		: "cc", "memory" );
 	return old;
 }
 
+#else /* __GNUC__ */
+
+static inline int
+_raw_compare_and_swap(volatile unsigned int *lock,
+		      unsigned int old, unsigned int new)
+{
+	asm volatile(
+		"	cs	%0,%3,0(%4)"
+		: "=d" (old), "=m" (*lock)
+		: "0" (old), "d" (new), "a" (lock), "m" (*lock)
+		: "cc", "memory" );
+	return old;
+}
+
+#endif /* __GNUC__ */
+
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
diff --git a/include/asm-s390/string.h b/include/asm-s390/string.h
index 23a4c39..d074673 100644
--- a/include/asm-s390/string.h
+++ b/include/asm-s390/string.h
@@ -60,12 +60,13 @@
 	register int r0 asm("0") = (char) c;
 	const void *ret = s + n;
 
-	asm volatile ("0: srst  %0,%1\n"
-		      "   jo    0b\n"
-		      "   jl	1f\n"
-		      "   la    %0,0\n"
-		      "1:"
-		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
+	asm volatile(
+		"0:	srst	%0,%1\n"
+		"	jo	0b\n"
+		"	jl	1f\n"
+		"	la	%0,0\n"
+		"1:"
+		: "+a" (ret), "+&a" (s) : "d" (r0) : "cc");
 	return (void *) ret;
 }
 
@@ -74,9 +75,10 @@
 	register int r0 asm("0") = (char) c;
 	const void *ret = s + n;
 
-	asm volatile ("0: srst  %0,%1\n"
-		      "   jo    0b\n"
-		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
+	asm volatile(
+		"0:	srst	%0,%1\n"
+		"	jo	0b\n"
+		: "+a" (ret), "+&a" (s) : "d" (r0) : "cc");
 	return (void *) ret;
 }
 
@@ -86,12 +88,13 @@
 	unsigned long dummy;
 	char *ret = dst;
 
-	asm volatile ("0: srst  %0,%1\n"
-		      "   jo    0b\n"
-		      "1: mvst  %0,%2\n"
-		      "   jo    1b"
-		      : "=&a" (dummy), "+a" (dst), "+a" (src)
-		      : "d" (r0), "0" (0) : "cc", "memory" );
+	asm volatile(
+		"0:	srst	%0,%1\n"
+		"	jo	0b\n"
+		"1:	mvst	%0,%2\n"
+		"	jo	1b"
+		: "=&a" (dummy), "+a" (dst), "+a" (src)
+		: "d" (r0), "0" (0) : "cc", "memory" );
 	return ret;
 }
 
@@ -100,10 +103,11 @@
 	register int r0 asm("0") = 0;
 	char *ret = dst;
 
-	asm volatile ("0: mvst  %0,%1\n"
-		      "   jo    0b"
-		      : "+&a" (dst), "+&a" (src) : "d" (r0)
-		      : "cc", "memory" );
+	asm volatile(
+		"0:	mvst	%0,%1\n"
+		"	jo	0b"
+		: "+&a" (dst), "+&a" (src) : "d" (r0)
+		: "cc", "memory");
 	return ret;
 }
 
@@ -112,9 +116,10 @@
 	register unsigned long r0 asm("0") = 0;
 	const char *tmp = s;
 
-	asm volatile ("0: srst  %0,%1\n"
-		      "   jo    0b"
-		      : "+d" (r0), "+a" (tmp) :  : "cc" );
+	asm volatile(
+		"0:	srst	%0,%1\n"
+		"	jo	0b"
+		: "+d" (r0), "+a" (tmp) :  : "cc");
 	return r0 - (unsigned long) s;
 }
 
@@ -124,9 +129,10 @@
 	const char *tmp = s;
 	const char *end = s + n;
 
-	asm volatile ("0: srst  %0,%1\n"
-		      "   jo    0b"
-		      : "+a" (end), "+a" (tmp) : "d" (r0)  : "cc" );
+	asm volatile(
+		"0:	srst	%0,%1\n"
+		"	jo	0b"
+		: "+a" (end), "+a" (tmp) : "d" (r0)  : "cc");
 	return end - s;
 }
 
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 1604004..ccbafe4 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -23,74 +23,68 @@
 
 extern struct task_struct *__switch_to(void *, void *);
 
-#ifdef __s390x__
-#define __FLAG_SHIFT 56
-#else /* ! __s390x__ */
-#define __FLAG_SHIFT 24
-#endif /* ! __s390x__ */
-
 static inline void save_fp_regs(s390_fp_regs *fpregs)
 {
-	asm volatile (
-		"   std   0,8(%1)\n"
-		"   std   2,24(%1)\n"
-		"   std   4,40(%1)\n"
-		"   std   6,56(%1)"
-		: "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory" );
+	asm volatile(
+		"	std	0,8(%1)\n"
+		"	std	2,24(%1)\n"
+		"	std	4,40(%1)\n"
+		"	std	6,56(%1)"
+		: "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory");
 	if (!MACHINE_HAS_IEEE)
 		return;
 	asm volatile(
-		"   stfpc 0(%1)\n"
-		"   std   1,16(%1)\n"
-		"   std   3,32(%1)\n"
-		"   std   5,48(%1)\n"
-		"   std   7,64(%1)\n"
-		"   std   8,72(%1)\n"
-		"   std   9,80(%1)\n"
-		"   std   10,88(%1)\n"
-		"   std   11,96(%1)\n"
-		"   std   12,104(%1)\n"
-		"   std   13,112(%1)\n"
-		"   std   14,120(%1)\n"
-		"   std   15,128(%1)\n"
-		: "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory" );
+		"	stfpc	0(%1)\n"
+		"	std	1,16(%1)\n"
+		"	std	3,32(%1)\n"
+		"	std	5,48(%1)\n"
+		"	std	7,64(%1)\n"
+		"	std	8,72(%1)\n"
+		"	std	9,80(%1)\n"
+		"	std	10,88(%1)\n"
+		"	std	11,96(%1)\n"
+		"	std	12,104(%1)\n"
+		"	std	13,112(%1)\n"
+		"	std	14,120(%1)\n"
+		"	std	15,128(%1)\n"
+		: "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory");
 }
 
 static inline void restore_fp_regs(s390_fp_regs *fpregs)
 {
-	asm volatile (
-		"   ld    0,8(%0)\n"
-		"   ld    2,24(%0)\n"
-		"   ld    4,40(%0)\n"
-		"   ld    6,56(%0)"
-		: : "a" (fpregs), "m" (*fpregs) );
+	asm volatile(
+		"	ld	0,8(%0)\n"
+		"	ld	2,24(%0)\n"
+		"	ld	4,40(%0)\n"
+		"	ld	6,56(%0)"
+		: : "a" (fpregs), "m" (*fpregs));
 	if (!MACHINE_HAS_IEEE)
 		return;
 	asm volatile(
-		"   lfpc  0(%0)\n"
-		"   ld    1,16(%0)\n"
-		"   ld    3,32(%0)\n"
-		"   ld    5,48(%0)\n"
-		"   ld    7,64(%0)\n"
-		"   ld    8,72(%0)\n"
-		"   ld    9,80(%0)\n"
-		"   ld    10,88(%0)\n"
-		"   ld    11,96(%0)\n"
-		"   ld    12,104(%0)\n"
-		"   ld    13,112(%0)\n"
-		"   ld    14,120(%0)\n"
-		"   ld    15,128(%0)\n"
-		: : "a" (fpregs), "m" (*fpregs) );
+		"	lfpc	0(%0)\n"
+		"	ld	1,16(%0)\n"
+		"	ld	3,32(%0)\n"
+		"	ld	5,48(%0)\n"
+		"	ld	7,64(%0)\n"
+		"	ld	8,72(%0)\n"
+		"	ld	9,80(%0)\n"
+		"	ld	10,88(%0)\n"
+		"	ld	11,96(%0)\n"
+		"	ld	12,104(%0)\n"
+		"	ld	13,112(%0)\n"
+		"	ld	14,120(%0)\n"
+		"	ld	15,128(%0)\n"
+		: : "a" (fpregs), "m" (*fpregs));
 }
 
 static inline void save_access_regs(unsigned int *acrs)
 {
-	asm volatile ("stam 0,15,0(%0)" : : "a" (acrs) : "memory" );
+	asm volatile("stam 0,15,0(%0)" : : "a" (acrs) : "memory");
 }
 
 static inline void restore_access_regs(unsigned int *acrs)
 {
-	asm volatile ("lam 0,15,0(%0)" : : "a" (acrs) );
+	asm volatile("lam 0,15,0(%0)" : : "a" (acrs));
 }
 
 #define switch_to(prev,next,last) do {					     \
@@ -126,7 +120,7 @@
 	account_vtime(prev);						     \
 } while (0)
 
-#define nop() __asm__ __volatile__ ("nop")
+#define nop() asm volatile("nop")
 
 #define xchg(ptr,x)							  \
 ({									  \
@@ -147,15 +141,15 @@
 		shift = (3 ^ (addr & 3)) << 3;
 		addr ^= addr & 3;
 		asm volatile(
-			"    l   %0,0(%4)\n"
-			"0:  lr  0,%0\n"
-			"    nr  0,%3\n"
-			"    or  0,%2\n"
-			"    cs  %0,0,0(%4)\n"
-			"    jl  0b\n"
+			"	l	%0,0(%4)\n"
+			"0:	lr	0,%0\n"
+			"	nr	0,%3\n"
+			"	or	0,%2\n"
+			"	cs	%0,0,0(%4)\n"
+			"	jl	0b\n"
 			: "=&d" (old), "=m" (*(int *) addr)
 			: "d" (x << shift), "d" (~(255 << shift)), "a" (addr),
-			  "m" (*(int *) addr) : "memory", "cc", "0" );
+			  "m" (*(int *) addr) : "memory", "cc", "0");
 		x = old >> shift;
 		break;
 	case 2:
@@ -163,36 +157,36 @@
 		shift = (2 ^ (addr & 2)) << 3;
 		addr ^= addr & 2;
 		asm volatile(
-			"    l   %0,0(%4)\n"
-			"0:  lr  0,%0\n"
-			"    nr  0,%3\n"
-			"    or  0,%2\n"
-			"    cs  %0,0,0(%4)\n"
-			"    jl  0b\n"
+			"	l	%0,0(%4)\n"
+			"0:	lr	0,%0\n"
+			"	nr	0,%3\n"
+			"	or	0,%2\n"
+			"	cs	%0,0,0(%4)\n"
+			"	jl	0b\n"
 			: "=&d" (old), "=m" (*(int *) addr)
 			: "d" (x << shift), "d" (~(65535 << shift)), "a" (addr),
-			  "m" (*(int *) addr) : "memory", "cc", "0" );
+			  "m" (*(int *) addr) : "memory", "cc", "0");
 		x = old >> shift;
 		break;
 	case 4:
-		asm volatile (
-			"    l   %0,0(%3)\n"
-			"0:  cs  %0,%2,0(%3)\n"
-			"    jl  0b\n"
+		asm volatile(
+			"	l	%0,0(%3)\n"
+			"0:	cs	%0,%2,0(%3)\n"
+			"	jl	0b\n"
 			: "=&d" (old), "=m" (*(int *) ptr)
 			: "d" (x), "a" (ptr), "m" (*(int *) ptr)
-			: "memory", "cc" );
+			: "memory", "cc");
 		x = old;
 		break;
 #ifdef __s390x__
 	case 8:
-		asm volatile (
-			"    lg  %0,0(%3)\n"
-			"0:  csg %0,%2,0(%3)\n"
-			"    jl  0b\n"
+		asm volatile(
+			"	lg	%0,0(%3)\n"
+			"0:	csg	%0,%2,0(%3)\n"
+			"	jl	0b\n"
 			: "=&d" (old), "=m" (*(long *) ptr)
 			: "d" (x), "a" (ptr), "m" (*(long *) ptr)
-			: "memory", "cc" );
+			: "memory", "cc");
 		x = old;
 		break;
 #endif /* __s390x__ */
@@ -224,55 +218,55 @@
 		shift = (3 ^ (addr & 3)) << 3;
 		addr ^= addr & 3;
 		asm volatile(
-			"    l   %0,0(%4)\n"
-			"0:  nr  %0,%5\n"
-                        "    lr  %1,%0\n"
-			"    or  %0,%2\n"
-			"    or  %1,%3\n"
-			"    cs  %0,%1,0(%4)\n"
-			"    jnl 1f\n"
-			"    xr  %1,%0\n"
-			"    nr  %1,%5\n"
-			"    jnz 0b\n"
+			"	l	%0,0(%4)\n"
+			"0:	nr	%0,%5\n"
+			"	lr	%1,%0\n"
+			"	or	%0,%2\n"
+			"	or	%1,%3\n"
+			"	cs	%0,%1,0(%4)\n"
+			"	jnl	1f\n"
+			"	xr	%1,%0\n"
+			"	nr	%1,%5\n"
+			"	jnz	0b\n"
 			"1:"
 			: "=&d" (prev), "=&d" (tmp)
 			: "d" (old << shift), "d" (new << shift), "a" (ptr),
 			  "d" (~(255 << shift))
-			: "memory", "cc" );
+			: "memory", "cc");
 		return prev >> shift;
 	case 2:
 		addr = (unsigned long) ptr;
 		shift = (2 ^ (addr & 2)) << 3;
 		addr ^= addr & 2;
 		asm volatile(
-			"    l   %0,0(%4)\n"
-			"0:  nr  %0,%5\n"
-                        "    lr  %1,%0\n"
-			"    or  %0,%2\n"
-			"    or  %1,%3\n"
-			"    cs  %0,%1,0(%4)\n"
-			"    jnl 1f\n"
-			"    xr  %1,%0\n"
-			"    nr  %1,%5\n"
-			"    jnz 0b\n"
+			"	l	%0,0(%4)\n"
+			"0:	nr	%0,%5\n"
+			"	lr	%1,%0\n"
+			"	or	%0,%2\n"
+			"	or	%1,%3\n"
+			"	cs	%0,%1,0(%4)\n"
+			"	jnl	1f\n"
+			"	xr	%1,%0\n"
+			"	nr	%1,%5\n"
+			"	jnz	0b\n"
 			"1:"
 			: "=&d" (prev), "=&d" (tmp)
 			: "d" (old << shift), "d" (new << shift), "a" (ptr),
 			  "d" (~(65535 << shift))
-			: "memory", "cc" );
+			: "memory", "cc");
 		return prev >> shift;
 	case 4:
-		asm volatile (
-			"    cs  %0,%2,0(%3)\n"
+		asm volatile(
+			"	cs	%0,%2,0(%3)\n"
 			: "=&d" (prev) : "0" (old), "d" (new), "a" (ptr)
-			: "memory", "cc" );
+			: "memory", "cc");
 		return prev;
 #ifdef __s390x__
 	case 8:
-		asm volatile (
-			"    csg %0,%2,0(%3)\n"
+		asm volatile(
+			"	csg	%0,%2,0(%3)\n"
 			: "=&d" (prev) : "0" (old), "d" (new), "a" (ptr)
-			: "memory", "cc" );
+			: "memory", "cc");
 		return prev;
 #endif /* __s390x__ */
         }
@@ -289,8 +283,8 @@
  * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
  */
 
-#define eieio()  __asm__ __volatile__ ( "bcr 15,0" : : : "memory" ) 
-# define SYNC_OTHER_CORES(x)   eieio() 
+#define eieio()	asm volatile("bcr 15,0" : : : "memory")
+#define SYNC_OTHER_CORES(x)   eieio()
 #define mb()    eieio()
 #define rmb()   eieio()
 #define wmb()   eieio()
@@ -307,117 +301,56 @@
 
 #ifdef __s390x__
 
-#define __ctl_load(array, low, high) ({ \
-	typedef struct { char _[sizeof(array)]; } addrtype; \
-	__asm__ __volatile__ ( \
-		"   bras  1,0f\n" \
-                "   lctlg 0,0,0(%0)\n" \
-		"0: ex    %1,0(1)" \
-		: : "a" (&array), "a" (((low)<<4)+(high)), \
-		    "m" (*(addrtype *)(array)) : "1" ); \
+#define __ctl_load(array, low, high) ({				\
+	typedef struct { char _[sizeof(array)]; } addrtype;	\
+	asm volatile(						\
+		"	lctlg	%1,%2,0(%0)\n"			\
+		: : "a" (&array), "i" (low), "i" (high),	\
+		    "m" (*(addrtype *)(array)));		\
 	})
 
-#define __ctl_store(array, low, high) ({ \
-	typedef struct { char _[sizeof(array)]; } addrtype; \
-	__asm__ __volatile__ ( \
-		"   bras  1,0f\n" \
-		"   stctg 0,0,0(%1)\n" \
-		"0: ex    %2,0(1)" \
-		: "=m" (*(addrtype *)(array)) \
-		: "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+#define __ctl_store(array, low, high) ({			\
+	typedef struct { char _[sizeof(array)]; } addrtype;	\
+	asm volatile(						\
+		"	stctg	%2,%3,0(%1)\n"			\
+		: "=m" (*(addrtype *)(array))			\
+		: "a" (&array), "i" (low), "i" (high));		\
 	})
 
-#define __ctl_set_bit(cr, bit) ({ \
-        __u8 __dummy[24]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctg 0,0,0(%1)\n" \
-                "    lctlg 0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    lg    0,0(%1)\n" \
-                "    ogr   0,%3\n"       /* set the bit */ \
-                "    stg   0,0(%1)\n" \
-                "1:  ex    %2,6(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-		: "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-		  "a" (cr*17), "a" (1L<<(bit)) \
-                : "cc", "0", "1" ); \
-        })
-
-#define __ctl_clear_bit(cr, bit) ({ \
-        __u8 __dummy[16]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctg 0,0,0(%1)\n" \
-                "    lctlg 0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    lg    0,0(%1)\n" \
-                "    ngr   0,%3\n"       /* set the bit */ \
-                "    stg   0,0(%1)\n" \
-                "1:  ex    %2,6(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-		: "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-		  "a" (cr*17), "a" (~(1L<<(bit))) \
-                : "cc", "0", "1" ); \
-        })
-
 #else /* __s390x__ */
 
-#define __ctl_load(array, low, high) ({ \
-	typedef struct { char _[sizeof(array)]; } addrtype; \
-	__asm__ __volatile__ ( \
-		"   bras  1,0f\n" \
-                "   lctl 0,0,0(%0)\n" \
-		"0: ex    %1,0(1)" \
-		: : "a" (&array), "a" (((low)<<4)+(high)), \
-		    "m" (*(addrtype *)(array)) : "1" ); \
+#define __ctl_load(array, low, high) ({				\
+	typedef struct { char _[sizeof(array)]; } addrtype;	\
+	asm volatile(						\
+		"	lctl	%1,%2,0(%0)\n"			\
+		: : "a" (&array), "i" (low), "i" (high),	\
+		    "m" (*(addrtype *)(array)));		\
+})
+
+#define __ctl_store(array, low, high) ({			\
+	typedef struct { char _[sizeof(array)]; } addrtype;	\
+	asm volatile(						\
+		"	stctl	%2,%3,0(%1)\n"			\
+		: "=m" (*(addrtype *)(array))			\
+		: "a" (&array), "i" (low), "i" (high));		\
 	})
 
-#define __ctl_store(array, low, high) ({ \
-	typedef struct { char _[sizeof(array)]; } addrtype; \
-	__asm__ __volatile__ ( \
-		"   bras  1,0f\n" \
-		"   stctl 0,0,0(%1)\n" \
-		"0: ex    %2,0(1)" \
-		: "=m" (*(addrtype *)(array)) \
-		: "a" (&array), "a" (((low)<<4)+(high)): "1" ); \
-	})
-
-#define __ctl_set_bit(cr, bit) ({ \
-        __u8 __dummy[16]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctl 0,0,0(%1)\n" \
-                "    lctl  0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    l     0,0(%1)\n" \
-                "    or    0,%3\n"       /* set the bit */ \
-                "    st    0,0(%1)\n" \
-                "1:  ex    %2,4(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-		: "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-		  "a" (cr*17), "a" (1<<(bit)) \
-                : "cc", "0", "1" ); \
-        })
-
-#define __ctl_clear_bit(cr, bit) ({ \
-        __u8 __dummy[16]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctl 0,0,0(%1)\n" \
-                "    lctl  0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    l     0,0(%1)\n" \
-                "    nr    0,%3\n"       /* set the bit */ \
-                "    st    0,0(%1)\n" \
-                "1:  ex    %2,4(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-		: "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-		  "a" (cr*17), "a" (~(1<<(bit))) \
-                : "cc", "0", "1" ); \
-        })
 #endif /* __s390x__ */
 
+#define __ctl_set_bit(cr, bit) ({	\
+	unsigned long __dummy;		\
+	__ctl_store(__dummy, cr, cr);	\
+	__dummy |= 1UL << (bit);	\
+	__ctl_load(__dummy, cr, cr);	\
+})
+
+#define __ctl_clear_bit(cr, bit) ({	\
+	unsigned long __dummy;		\
+	__ctl_store(__dummy, cr, cr);	\
+	__dummy &= ~(1UL << (bit));	\
+	__ctl_load(__dummy, cr, cr);	\
+})
+
 #include <linux/irqflags.h>
 
 /*
@@ -427,8 +360,7 @@
 static inline void
 __set_psw_mask(unsigned long mask)
 {
-	local_save_flags(mask);
-	__load_psw_mask(mask);
+	__load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8)));
 }
 
 #define local_mcck_enable()  __set_psw_mask(PSW_KERNEL_BITS)
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
index 5d0332a..4df4a41 100644
--- a/include/asm-s390/timex.h
+++ b/include/asm-s390/timex.h
@@ -15,20 +15,21 @@
 
 typedef unsigned long long cycles_t;
 
-static inline cycles_t get_cycles(void)
-{
-	cycles_t cycles;
-
-	__asm__ __volatile__ ("stck 0(%1)" : "=m" (cycles) : "a" (&cycles) : "cc");
-	return cycles >> 2;
-}
-
 static inline unsigned long long get_clock (void)
 {
 	unsigned long long clk;
 
-	__asm__ __volatile__ ("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+	asm volatile("stck %0" : "=Q" (clk) : : "cc");
+#else /* __GNUC__ */
+	asm volatile("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
+#endif /* __GNUC__ */
 	return clk;
 }
 
+static inline cycles_t get_cycles(void)
+{
+	return (cycles_t) get_clock() >> 2;
+}
+
 #endif
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index 73cd85b..fa4dc91 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -25,7 +25,7 @@
  */
 
 #define local_flush_tlb() \
-do {  __asm__ __volatile__("ptlb": : :"memory"); } while (0)
+do {  asm volatile("ptlb": : :"memory"); } while (0)
 
 #ifndef CONFIG_SMP
 
@@ -68,24 +68,24 @@
 
 static inline void global_flush_tlb(void)
 {
+	register unsigned long reg2 asm("2");
+	register unsigned long reg3 asm("3");
+	register unsigned long reg4 asm("4");
+	long dummy;
+
 #ifndef __s390x__
 	if (!MACHINE_HAS_CSP) {
 		smp_ptlb_all();
 		return;
 	}
 #endif /* __s390x__ */
-	{
-		register unsigned long addr asm("4");
-		long dummy;
 
-		dummy = 0;
-		addr = ((unsigned long) &dummy) + 1;
-		__asm__ __volatile__ (
-			"    slr  2,2\n"
-			"    slr  3,3\n"
-			"    csp  2,%0"
-			: : "a" (addr), "m" (dummy) : "cc", "2", "3" );
-	}
+	dummy = 0;
+	reg2 = reg3 = 0;
+	reg4 = ((unsigned long) &dummy) + 1;
+	asm volatile(
+		"	csp	%0,%2"
+		: : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
 }
 
 /*
@@ -102,9 +102,9 @@
 	if (unlikely(cpus_empty(mm->cpu_vm_mask)))
 		return;
 	if (MACHINE_HAS_IDTE) {
-		asm volatile (".insn rrf,0xb98e0000,0,%0,%1,0"
-			      : : "a" (2048),
-			      "a" (__pa(mm->pgd)&PAGE_MASK) : "cc" );
+		asm volatile(
+			"	.insn	rrf,0xb98e0000,0,%0,%1,0"
+			: : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc");
 		return;
 	}
 	preempt_disable();
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index e2047b0..72ae4ef 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -38,25 +38,14 @@
 #define get_ds()        (KERNEL_DS)
 #define get_fs()        (current->thread.mm_segment)
 
-#ifdef __s390x__
 #define set_fs(x) \
 ({									\
 	unsigned long __pto;						\
 	current->thread.mm_segment = (x);				\
 	__pto = current->thread.mm_segment.ar4 ?			\
 		S390_lowcore.user_asce : S390_lowcore.kernel_asce;	\
-	asm volatile ("lctlg 7,7,%0" : : "m" (__pto) );			\
+	__ctl_load(__pto, 7, 7);					\
 })
-#else /* __s390x__ */
-#define set_fs(x) \
-({									\
-	unsigned long __pto;						\
-	current->thread.mm_segment = (x);				\
-	__pto = current->thread.mm_segment.ar4 ?			\
-		S390_lowcore.user_asce : S390_lowcore.kernel_asce;	\
-	asm volatile ("lctl  7,7,%0" : : "m" (__pto) );			\
-})
-#endif /* __s390x__ */
 
 #define segment_eq(a,b) ((a).ar4 == (b).ar4)
 
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index d49c54c..0361ac5 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -355,145 +355,145 @@
 
 #define _svc_clobber "1", "cc", "memory"
 
-#define _syscall0(type,name)				     \
-type name(void) {					     \
-	register long __svcres asm("2");		     \
-	long __res;					     \
-	__asm__ __volatile__ (				     \
-		"    .if %1 < 256\n"			     \
-		"    svc %b1\n"				     \
-		"    .else\n"				     \
-		"    la  %%r1,%1\n"			     \
-		"    svc 0\n"				     \
-		"    .endif"				     \
-		: "=d" (__svcres)			     \
-		: "i" (__NR_##name)			     \
-		: _svc_clobber );			     \
-	__res = __svcres;				     \
-	__syscall_return(type,__res);			     \
+#define _syscall0(type,name)					\
+type name(void) {						\
+	register long __svcres asm("2");			\
+	long __res;						\
+	asm volatile(						\
+		"	.if	%1 < 256\n"			\
+		"	svc	%b1\n"				\
+		"	.else\n"				\
+		"	la	%%r1,%1\n"			\
+		"	svc	0\n"				\
+		"	.endif"					\
+		: "=d" (__svcres)				\
+		: "i" (__NR_##name)				\
+		: _svc_clobber);				\
+	__res = __svcres;					\
+	__syscall_return(type,__res);				\
 }
 
-#define _syscall1(type,name,type1,arg1)			     \
-type name(type1 arg1) {					     \
-	register type1 __arg1 asm("2") = arg1;		     \
-	register long __svcres asm("2");		     \
-	long __res;					     \
-	__asm__ __volatile__ (				     \
-		"    .if %1 < 256\n"			     \
-		"    svc %b1\n"				     \
-		"    .else\n"				     \
-		"    la  %%r1,%1\n"			     \
-		"    svc 0\n"				     \
-		"    .endif"				     \
-		: "=d" (__svcres)			     \
-		: "i" (__NR_##name),			     \
-		  "0" (__arg1)				     \
-		: _svc_clobber );			     \
-	__res = __svcres;				     \
-	__syscall_return(type,__res);			     \
+#define _syscall1(type,name,type1,arg1)				\
+type name(type1 arg1) {						\
+	register type1 __arg1 asm("2") = arg1;			\
+	register long __svcres asm("2");			\
+	long __res;						\
+	asm volatile(						\
+		"	.if	%1 < 256\n"			\
+		"	svc	%b1\n"				\
+		"	.else\n"				\
+		"	la	%%r1,%1\n"			\
+		"	svc	0\n"				\
+		"	.endif"					\
+		: "=d" (__svcres)				\
+		: "i" (__NR_##name),				\
+		  "0" (__arg1)					\
+		: _svc_clobber);				\
+	__res = __svcres;					\
+	__syscall_return(type,__res);				\
 }
 
-#define _syscall2(type,name,type1,arg1,type2,arg2)	     \
-type name(type1 arg1, type2 arg2) {			     \
-	register type1 __arg1 asm("2") = arg1;		     \
-	register type2 __arg2 asm("3") = arg2;		     \
-	register long __svcres asm("2");		     \
-	long __res;					     \
-	__asm__ __volatile__ (				     \
-		"    .if %1 < 256\n"			     \
-		"    svc %b1\n"				     \
-		"    .else\n"				     \
-		"    la %%r1,%1\n"			     \
-		"    svc 0\n"				     \
-		"    .endif"				     \
-		: "=d" (__svcres)			     \
-		: "i" (__NR_##name),			     \
-		  "0" (__arg1),				     \
-		  "d" (__arg2)				     \
-		: _svc_clobber );			     \
-	__res = __svcres;				     \
-	__syscall_return(type,__res);			     \
+#define _syscall2(type,name,type1,arg1,type2,arg2)		\
+type name(type1 arg1, type2 arg2) {				\
+	register type1 __arg1 asm("2") = arg1;			\
+	register type2 __arg2 asm("3") = arg2;			\
+	register long __svcres asm("2");			\
+	long __res;						\
+	asm volatile(						\
+		"	.if	%1 < 256\n"			\
+		"	svc	%b1\n"				\
+		"	.else\n"				\
+		"	la	%%r1,%1\n"			\
+		"	svc	0\n"				\
+		"	.endif"					\
+		: "=d" (__svcres)				\
+		: "i" (__NR_##name),				\
+		  "0" (__arg1),					\
+		  "d" (__arg2)					\
+		: _svc_clobber );				\
+	__res = __svcres;					\
+	__syscall_return(type,__res);				\
 }
 
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)\
-type name(type1 arg1, type2 arg2, type3 arg3) {		     \
-	register type1 __arg1 asm("2") = arg1;		     \
-	register type2 __arg2 asm("3") = arg2;		     \
-	register type3 __arg3 asm("4") = arg3;		     \
-	register long __svcres asm("2");		     \
-	long __res;					     \
-	__asm__ __volatile__ (				     \
-		"    .if %1 < 256\n"			     \
-		"    svc %b1\n"				     \
-		"    .else\n"				     \
-		"    la  %%r1,%1\n"			     \
-		"    svc 0\n"				     \
-		"    .endif"				     \
-		: "=d" (__svcres)			     \
-		: "i" (__NR_##name),			     \
-		  "0" (__arg1),				     \
-		  "d" (__arg2),				     \
-		  "d" (__arg3)				     \
-		: _svc_clobber );			     \
-	__res = __svcres;				     \
-	__syscall_return(type,__res);			     \
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)	\
+type name(type1 arg1, type2 arg2, type3 arg3) {			\
+	register type1 __arg1 asm("2") = arg1;			\
+	register type2 __arg2 asm("3") = arg2;			\
+	register type3 __arg3 asm("4") = arg3;			\
+	register long __svcres asm("2");			\
+	long __res;						\
+	asm volatile(						\
+		"	.if	%1 < 256\n"			\
+		"	svc	%b1\n"				\
+		"	.else\n"				\
+		"	la	%%r1,%1\n"			\
+		"	svc	0\n"				\
+		"	.endif"					\
+		: "=d" (__svcres)				\
+		: "i" (__NR_##name),				\
+		  "0" (__arg1),					\
+		  "d" (__arg2),					\
+		  "d" (__arg3)					\
+		: _svc_clobber);				\
+	__res = __svcres;					\
+	__syscall_return(type,__res);				\
 }
 
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,\
-		  type4,name4)				     \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {  \
-	register type1 __arg1 asm("2") = arg1;		     \
-	register type2 __arg2 asm("3") = arg2;		     \
-	register type3 __arg3 asm("4") = arg3;		     \
-	register type4 __arg4 asm("5") = arg4;		     \
-	register long __svcres asm("2");		     \
-	long __res;					     \
-	__asm__ __volatile__ (				     \
-		"    .if %1 < 256\n"			     \
-		"    svc %b1\n"				     \
-		"    .else\n"				     \
-		"    la  %%r1,%1\n"			     \
-		"    svc 0\n"				     \
-		"    .endif"				     \
-		: "=d" (__svcres)			     \
-		: "i" (__NR_##name),			     \
-		  "0" (__arg1),				     \
-		  "d" (__arg2),				     \
-		  "d" (__arg3),				     \
-		  "d" (__arg4)				     \
-		: _svc_clobber );			     \
-	__res = __svcres;				     \
-	__syscall_return(type,__res);			     \
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,	\
+		  type4,name4)					\
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {	\
+	register type1 __arg1 asm("2") = arg1;			\
+	register type2 __arg2 asm("3") = arg2;			\
+	register type3 __arg3 asm("4") = arg3;			\
+	register type4 __arg4 asm("5") = arg4;			\
+	register long __svcres asm("2");			\
+	long __res;						\
+	asm volatile(						\
+		"	.if	%1 < 256\n"			\
+		"	svc	%b1\n"				\
+		"	.else\n"				\
+		"	la	%%r1,%1\n"			\
+		"	svc	0\n"				\
+		"	.endif"					\
+		: "=d" (__svcres)				\
+		: "i" (__NR_##name),				\
+		  "0" (__arg1),					\
+		  "d" (__arg2),					\
+		  "d" (__arg3),					\
+		  "d" (__arg4)					\
+		: _svc_clobber);				\
+	__res = __svcres;					\
+	__syscall_return(type,__res);				\
 }
 
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,\
-		  type4,name4,type5,name5)		     \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,    \
-	  type5 arg5) {					     \
-	register type1 __arg1 asm("2") = arg1;		     \
-	register type2 __arg2 asm("3") = arg2;		     \
-	register type3 __arg3 asm("4") = arg3;		     \
-	register type4 __arg4 asm("5") = arg4;		     \
-	register type5 __arg5 asm("6") = arg5;		     \
-	register long __svcres asm("2");		     \
-	long __res;					     \
-	__asm__ __volatile__ (				     \
-		"    .if %1 < 256\n"			     \
-		"    svc %b1\n"				     \
-		"    .else\n"				     \
-		"    la  %%r1,%1\n"			     \
-		"    svc 0\n"				     \
-		"    .endif"				     \
-		: "=d" (__svcres)			     \
-		: "i" (__NR_##name),			     \
-		  "0" (__arg1),				     \
-		  "d" (__arg2),				     \
-		  "d" (__arg3),				     \
-		  "d" (__arg4),				     \
-		  "d" (__arg5)				     \
-		: _svc_clobber );			     \
-	__res = __svcres;				     \
-	__syscall_return(type,__res);			     \
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,	\
+		  type4,name4,type5,name5)			\
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,	\
+	  type5 arg5) {						\
+	register type1 __arg1 asm("2") = arg1;			\
+	register type2 __arg2 asm("3") = arg2;			\
+	register type3 __arg3 asm("4") = arg3;			\
+	register type4 __arg4 asm("5") = arg4;			\
+	register type5 __arg5 asm("6") = arg5;			\
+	register long __svcres asm("2");			\
+	long __res;						\
+	asm volatile(						\
+		"	.if	%1 < 256\n"			\
+		"	svc	%b1\n"				\
+		"	.else\n"				\
+		"	la	%%r1,%1\n"			\
+		"	svc	0\n"				\
+		"	.endif"					\
+		: "=d" (__svcres)				\
+		: "i" (__NR_##name),				\
+		  "0" (__arg1),					\
+		  "d" (__arg2),					\
+		  "d" (__arg3),					\
+		  "d" (__arg4),					\
+		  "d" (__arg5)					\
+		: _svc_clobber);				\
+	__res = __svcres;					\
+	__syscall_return(type,__res);				\
 }
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 4862daf..188f726 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -274,12 +274,6 @@
 	return(pte_mknewprot(pte)); 
 }
 
-static inline pte_t pte_mkexec(pte_t pte)
-{ 
-	pte_set_bits(pte, _PAGE_USER);
-	return(pte_mknewprot(pte)); 
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 { 
 	pte_set_bits(pte, _PAGE_DIRTY);
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index b6da83d..10174b1 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -55,13 +55,6 @@
 extern struct dma_mapping_ops* dma_ops;
 extern int iommu_merge;
 
-static inline int valid_dma_direction(int dma_direction)
-{
-	return ((dma_direction == DMA_BIDIRECTIONAL) ||
-		(dma_direction == DMA_TO_DEVICE) ||
-		(dma_direction == DMA_FROM_DEVICE));
-}
-
 static inline int dma_mapping_error(dma_addr_t dma_addr)
 {
 	if (dma_ops->mapping_error)
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 1df2ac3..f7a52e1 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -58,6 +58,7 @@
 header-y += fadvise.h
 header-y += fd.h
 header-y += fdreg.h
+header-y += fib_rules.h
 header-y += ftape-header-segment.h
 header-y += ftape-vendors.h
 header-y += fuse.h
@@ -70,6 +71,7 @@
 header-y += i2c-dev.h
 header-y += i8k.h
 header-y += icmp.h
+header-y += if_addr.h
 header-y += if_arcnet.h
 header-y += if_arp.h
 header-y += if_bonding.h
@@ -79,6 +81,7 @@
 header-y += if.h
 header-y += if_hippi.h
 header-y += if_infiniband.h
+header-y += if_link.h
 header-y += if_packet.h
 header-y += if_plip.h
 header-y += if_ppp.h
@@ -110,6 +113,7 @@
 header-y += mqueue.h
 header-y += mtio.h
 header-y += ncp_no.h
+header-y += neighbour.h
 header-y += netfilter_arp.h
 header-y += netrom.h
 header-y += nfs2.h
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 6ba3aa8..75b8bac 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -88,15 +88,7 @@
 #include <asm/byteorder.h>
 
 struct ddpehdr {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-	__u16	deh_len:10,
-		deh_hops:4,
-		deh_pad:2;
-#else
-	__u16	deh_pad:2,
-		deh_hops:4,
-		deh_len:10;
-#endif
+	__be16	deh_len_hops;	/* lower 10 bits are length, next 4 - hops */
 	__be16	deh_sum;
 	__be16	deh_dnet;
 	__be16	deh_snet;
@@ -112,36 +104,6 @@
 	return (struct ddpehdr *)skb->h.raw;
 }
 
-/*
- *	Don't drop the struct into the struct above.  You'll get some
- *	surprise padding.
- */
-struct ddpebits {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-	__u16	deh_len:10,
-		deh_hops:4,
-		deh_pad:2;
-#else
-	__u16	deh_pad:2,
-		deh_hops:4,
-		deh_len:10;
-#endif
-};
-
-/* Short form header */
-struct ddpshdr {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-	__u16	dsh_len:10,
-		dsh_pad:6;
-#else
-	__u16	dsh_pad:6,
-		dsh_len:10;
-#endif
-	__u8	dsh_dport;
-	__u8	dsh_sport;
-	/* And netatalk apps expect to stick the type in themselves */
-};
-
 /* AppleTalk AARP headers */
 struct elapaarp {
 	__be16	hw_type;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 40a6c26..42719d0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -95,6 +95,12 @@
 #define AUDIT_MAC_POLICY_LOAD	1403	/* Policy file load */
 #define AUDIT_MAC_STATUS	1404	/* Changed enforcing,permissive,off */
 #define AUDIT_MAC_CONFIG_CHANGE	1405	/* Changes to booleans */
+#define AUDIT_MAC_UNLBL_ACCEPT	1406	/* NetLabel: allow unlabeled traffic */
+#define AUDIT_MAC_UNLBL_DENY	1407	/* NetLabel: deny unlabeled traffic */
+#define AUDIT_MAC_CIPSOV4_ADD	1408	/* NetLabel: add CIPSOv4 DOI entry */
+#define AUDIT_MAC_CIPSOV4_DEL	1409	/* NetLabel: del CIPSOv4 DOI entry */
+#define AUDIT_MAC_MAP_ADD	1410	/* NetLabel: add LSM domain mapping */
+#define AUDIT_MAC_MAP_DEL	1411	/* NetLabel: del LSM domain mapping */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c773ee5..cfde8b3 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -417,9 +417,9 @@
 	unsigned int		sg_timeout;
 	unsigned int		sg_reserved_size;
 	int			node;
-
+#ifdef CONFIG_BLK_DEV_IO_TRACE
 	struct blk_trace	*blk_trace;
-
+#endif
 	/*
 	 * reserved for flush operations
 	 */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 060b961..0780de4 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -14,7 +14,7 @@
 # define __releases(x)	__attribute__((context(1,0)))
 # define __acquire(x)	__context__(1)
 # define __release(x)	__context__(-1)
-# define __cond_lock(x)	((x) ? ({ __context__(1); 1; }) : 0)
+# define __cond_lock(x,c)	((c) ? ({ __acquire(x); 1; }) : 0)
 extern void __chk_user_ptr(void __user *);
 extern void __chk_io_ptr(void __iomem *);
 #else
@@ -31,7 +31,7 @@
 # define __releases(x)
 # define __acquire(x) (void)0
 # define __release(x) (void)0
-# define __cond_lock(x) (x)
+# define __cond_lock(x,c) (c)
 #endif
 
 #ifdef __KERNEL__
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 9354722..4d8adf6 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -63,6 +63,8 @@
 	return current->flags & PF_SPREAD_SLAB;
 }
 
+extern void cpuset_track_online_nodes(void);
+
 #else /* !CONFIG_CPUSETS */
 
 static inline int cpuset_init_early(void) { return 0; }
@@ -126,6 +128,8 @@
 	return 0;
 }
 
+static inline void cpuset_track_online_nodes(void) {}
+
 #endif /* !CONFIG_CPUSETS */
 
 #endif /* _LINUX_CPUSET_H */
diff --git a/include/linux/cramfs_fs.h b/include/linux/cramfs_fs.h
index a41f384..1dba681 100644
--- a/include/linux/cramfs_fs.h
+++ b/include/linux/cramfs_fs.h
@@ -87,6 +87,6 @@
 /* Uncompression interfaces to the underlying zlib */
 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);
 int cramfs_uncompress_init(void);
-int cramfs_uncompress_exit(void);
+void cramfs_uncompress_exit(void);
 
 #endif
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 635690c..ff203c4 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -24,6 +24,13 @@
 #define DMA_28BIT_MASK	0x000000000fffffffULL
 #define DMA_24BIT_MASK	0x0000000000ffffffULL
 
+static inline int valid_dma_direction(int dma_direction)
+{
+	return ((dma_direction == DMA_BIDIRECTIONAL) ||
+		(dma_direction == DMA_TO_DEVICE) ||
+		(dma_direction == DMA_FROM_DEVICE));
+}
+
 #include <asm/dma-mapping.h>
 
 /* Backwards compat, remove in 2.7.x */
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index b2cd207..38dc403 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -27,7 +27,8 @@
 	DMI_DEV_TYPE_ETHERNET,
 	DMI_DEV_TYPE_TOKENRING,
 	DMI_DEV_TYPE_SOUND,
-	DMI_DEV_TYPE_IPMI = -1
+	DMI_DEV_TYPE_IPMI = -1,
+	DMI_DEV_TYPE_OEM_STRING = -2
 };
 
 struct dmi_header {
diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h
index 408118a..92f8d4f 100644
--- a/include/linux/errqueue.h
+++ b/include/linux/errqueue.h
@@ -38,7 +38,7 @@
 	} header;
 	struct sock_extended_err	ee;
 	u16				addr_offset;
-	u16				port;
+	__be16				port;
 };
 
 #endif
diff --git a/include/linux/file.h b/include/linux/file.h
index 9f7c251..74183e6 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -112,5 +112,6 @@
 
 struct files_struct *get_files_struct(struct task_struct *);
 void FASTCALL(put_files_struct(struct files_struct *fs));
+void reset_files_struct(struct task_struct *, struct files_struct *);
 
 #endif /* __LINUX_FILE_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8f74dfb..6eafbe3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -553,7 +553,9 @@
 	unsigned int		i_flags;
 
 	atomic_t		i_writecount;
+#ifdef CONFIG_SECURITY
 	void			*i_security;
+#endif
 	void			*i_private; /* fs or device private pointer */
 #ifdef __NEED_I_SIZE_ORDERED
 	seqcount_t		i_size_seqcount;
@@ -645,7 +647,6 @@
 	rwlock_t lock;          /* protects pid, uid, euid fields */
 	int pid;		/* pid or -pgrp where SIGIO should be sent */
 	uid_t uid, euid;	/* uid/euid of process setting the owner */
-	void *security;
 	int signum;		/* posix.1b rt signal to be delivered on IO */
 };
 
@@ -688,8 +689,9 @@
 	struct file_ra_state	f_ra;
 
 	unsigned long		f_version;
+#ifdef CONFIG_SECURITY
 	void			*f_security;
-
+#endif
 	/* needed for tty driver, and maybe others */
 	void			*private_data;
 
@@ -877,7 +879,9 @@
 	int			s_syncing;
 	int			s_need_sync_fs;
 	atomic_t		s_active;
+#ifdef CONFIG_SECURITY
 	void                    *s_security;
+#endif
 	struct xattr_handler	**s_xattr;
 
 	struct list_head	s_inodes;	/* all inodes */
@@ -1143,9 +1147,10 @@
 
 	int (*show_options)(struct seq_file *, struct vfsmount *);
 	int (*show_stats)(struct seq_file *, struct vfsmount *);
-
+#ifdef CONFIG_QUOTA
 	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+#endif
 };
 
 /* Inode state bits.  Protected by inode_lock. */
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h
new file mode 100644
index 0000000..80764f4
--- /dev/null
+++ b/include/linux/generic_acl.h
@@ -0,0 +1,36 @@
+/*
+ * fs/generic_acl.c
+ *
+ * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef GENERIC_ACL_H
+#define GENERIC_ACL_H
+
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
+
+/**
+ * struct generic_acl_operations  -  filesystem operations
+ *
+ * Filesystems must make these operations available to the generic
+ * operations.
+ */
+struct generic_acl_operations {
+	struct posix_acl *(*getacl)(struct inode *, int);
+	void (*setacl)(struct inode *, int, struct posix_acl *);
+};
+
+size_t generic_acl_list(struct inode *, struct generic_acl_operations *, int,
+			char *, size_t);
+int generic_acl_get(struct inode *, struct generic_acl_operations *, int,
+		    void *, size_t);
+int generic_acl_set(struct inode *, struct generic_acl_operations *, int,
+		    const void *, size_t);
+int generic_acl_init(struct inode *, struct inode *,
+		     struct generic_acl_operations *);
+int generic_acl_chmod(struct inode *, struct generic_acl_operations *);
+
+#endif
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index d5ebbb2..d4b3339 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -11,95 +11,46 @@
 #ifndef __HDLC_H
 #define __HDLC_H
 
-#define GENERIC_HDLC_VERSION 4	/* For synchronization with sethdlc utility */
-
-#define CLOCK_DEFAULT   0	/* Default setting */
-#define CLOCK_EXT	1	/* External TX and RX clock - DTE */
-#define CLOCK_INT	2	/* Internal TX and RX clock - DCE */
-#define CLOCK_TXINT	3	/* Internal TX and external RX clock */
-#define CLOCK_TXFROMRX	4	/* TX clock derived from external RX clock */
-
-
-#define ENCODING_DEFAULT	0 /* Default setting */
-#define ENCODING_NRZ		1
-#define ENCODING_NRZI		2
-#define ENCODING_FM_MARK	3
-#define ENCODING_FM_SPACE	4
-#define ENCODING_MANCHESTER	5
-
-
-#define PARITY_DEFAULT		0 /* Default setting */
-#define PARITY_NONE		1 /* No parity */
-#define PARITY_CRC16_PR0	2 /* CRC16, initial value 0x0000 */
-#define PARITY_CRC16_PR1	3 /* CRC16, initial value 0xFFFF */
-#define PARITY_CRC16_PR0_CCITT	4 /* CRC16, initial 0x0000, ITU-T version */
-#define PARITY_CRC16_PR1_CCITT	5 /* CRC16, initial 0xFFFF, ITU-T version */
-#define PARITY_CRC32_PR0_CCITT	6 /* CRC32, initial value 0x00000000 */
-#define PARITY_CRC32_PR1_CCITT	7 /* CRC32, initial value 0xFFFFFFFF */
-
-#define LMI_DEFAULT		0 /* Default setting */
-#define LMI_NONE		1 /* No LMI, all PVCs are static */
-#define LMI_ANSI		2 /* ANSI Annex D */
-#define LMI_CCITT		3 /* ITU-T Annex A */
-#define LMI_CISCO		4 /* The "original" LMI, aka Gang of Four */
 
 #define HDLC_MAX_MTU 1500	/* Ethernet 1500 bytes */
+#if 0
 #define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */
+#else
+#define HDLC_MAX_MRU 1600 /* as required for FR network */
+#endif
 
 
 #ifdef __KERNEL__
 
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
-#include <net/syncppp.h>
 #include <linux/hdlc/ioctl.h>
 
 
-typedef struct {		/* Used in Cisco and PPP mode */
-	u8 address;
-	u8 control;
-	u16 protocol;
-}__attribute__ ((packed)) hdlc_header;
-
-
-
-typedef struct {
-	u32 type;		/* code */
-	u32 par1;
-	u32 par2;
-	u16 rel;		/* reliability */
-	u32 time;
-}__attribute__ ((packed)) cisco_packet;
-#define	CISCO_PACKET_LEN	18
-#define	CISCO_BIG_PACKET_LEN	20
-
-
-
-typedef struct pvc_device_struct {
-	struct net_device *master;
-	struct net_device *main;
-	struct net_device *ether; /* bridged Ethernet interface */
-	struct pvc_device_struct *next;	/* Sorted in ascending DLCI order */
-	int dlci;
-	int open_count;
-
-	struct {
-		unsigned int new: 1;
-		unsigned int active: 1;
-		unsigned int exist: 1;
-		unsigned int deleted: 1;
-		unsigned int fecn: 1;
-		unsigned int becn: 1;
-		unsigned int bandwidth;	/* Cisco LMI reporting only */
-	}state;
-}pvc_device;
-
-
-
-typedef struct hdlc_device_struct {
-	/* To be initialized by hardware driver */
+/* Used by all network devices here, pointed to by netdev_priv(dev) */
+struct hdlc_device_desc {
+	int (*netif_rx)(struct sk_buff *skb);
 	struct net_device_stats stats;
+};
 
+/* This structure is a private property of HDLC protocols.
+   Hardware drivers have no interest here */
+
+struct hdlc_proto {
+	int (*open)(struct net_device *dev);
+	void (*close)(struct net_device *dev);
+	void (*start)(struct net_device *dev); /* if open & DCD */
+	void (*stop)(struct net_device *dev); /* if open & !DCD */
+	void (*detach)(struct net_device *dev);
+	int (*ioctl)(struct net_device *dev, struct ifreq *ifr);
+	unsigned short (*type_trans)(struct sk_buff *skb,
+				     struct net_device *dev);
+	struct module *module;
+	struct hdlc_proto *next; /* next protocol in the list */
+};
+
+
+typedef struct hdlc_device {
 	/* used by HDLC layer to take control over HDLC device from hw driver*/
 	int (*attach)(struct net_device *dev,
 		      unsigned short encoding, unsigned short parity);
@@ -107,82 +58,18 @@
 	/* hardware driver must handle this instead of dev->hard_start_xmit */
 	int (*xmit)(struct sk_buff *skb, struct net_device *dev);
 
-
 	/* Things below are for HDLC layer internal use only */
-	struct {
-		int (*open)(struct net_device *dev);
-		void (*close)(struct net_device *dev);
-
-		/* if open & DCD */
-		void (*start)(struct net_device *dev);
-		/* if open & !DCD */
-		void (*stop)(struct net_device *dev);
-
-		void (*detach)(struct hdlc_device_struct *hdlc);
-		int (*netif_rx)(struct sk_buff *skb);
-		unsigned short (*type_trans)(struct sk_buff *skb,
-					     struct net_device *dev);
-		int id;		/* IF_PROTO_HDLC/CISCO/FR/etc. */
-	}proto;
-
+	const struct hdlc_proto *proto;
 	int carrier;
 	int open;
 	spinlock_t state_lock;
-
-	union {
-		struct {
-			fr_proto settings;
-			pvc_device *first_pvc;
-			int dce_pvc_count;
-
-			struct timer_list timer;
-			unsigned long last_poll;
-			int reliable;
-			int dce_changed;
-			int request;
-			int fullrep_sent;
-			u32 last_errors; /* last errors bit list */
-			u8 n391cnt;
-			u8 txseq; /* TX sequence number */
-			u8 rxseq; /* RX sequence number */
-		}fr;
-
-		struct {
-			cisco_proto settings;
-
-			struct timer_list timer;
-			unsigned long last_poll;
-			int up;
-			int request_sent;
-			u32 txseq; /* TX sequence number */
-			u32 rxseq; /* RX sequence number */
-		}cisco;
-
-		struct {
-			raw_hdlc_proto settings;
-		}raw_hdlc;
-
-		struct {
-			struct ppp_device pppdev;
-			struct ppp_device *syncppp_ptr;
-			int (*old_change_mtu)(struct net_device *dev,
-					      int new_mtu);
-		}ppp;
-	}state;
+	void *state;
 	void *priv;
 }hdlc_device;
 
 
 
-int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr);
-
-
-/* Exported from hdlc.o */
+/* Exported from hdlc module */
 
 /* Called by hardware driver when a user requests HDLC service */
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
@@ -191,17 +78,21 @@
 #define register_hdlc_device(dev)	register_netdev(dev)
 void unregister_hdlc_device(struct net_device *dev);
 
+
+void register_hdlc_protocol(struct hdlc_proto *proto);
+void unregister_hdlc_protocol(struct hdlc_proto *proto);
+
 struct net_device *alloc_hdlcdev(void *priv);
 
-static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
+
+static __inline__ struct hdlc_device_desc* dev_to_desc(struct net_device *dev)
 {
 	return netdev_priv(dev);
 }
 
-
-static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
+static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
 {
-	return (pvc_device*)dev->priv;
+	return netdev_priv(dev) + sizeof(struct hdlc_device_desc);
 }
 
 
@@ -225,18 +116,14 @@
 /* Must be called by hardware driver when HDLC device is being closed */
 void hdlc_close(struct net_device *dev);
 
+int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
+			 int (*rx)(struct sk_buff *skb), size_t size);
 /* May be used by hardware driver to gain control over HDLC device */
-static __inline__ void hdlc_proto_detach(hdlc_device *hdlc)
-{
-	if (hdlc->proto.detach)
-		hdlc->proto.detach(hdlc);
-	hdlc->proto.detach = NULL;
-}
-
+void detach_hdlc_protocol(struct net_device *dev);
 
 static __inline__ struct net_device_stats *hdlc_stats(struct net_device *dev)
 {
-	return &dev_to_hdlc(dev)->stats;
+	return &dev_to_desc(dev)->stats;
 }
 
 
@@ -248,8 +135,8 @@
 	skb->mac.raw  = skb->data;
 	skb->dev      = dev;
 
-	if (hdlc->proto.type_trans)
-		return hdlc->proto.type_trans(skb, dev);
+	if (hdlc->proto->type_trans)
+		return hdlc->proto->type_trans(skb, dev);
 	else
 		return htons(ETH_P_HDLC);
 }
diff --git a/include/linux/hdlc/ioctl.h b/include/linux/hdlc/ioctl.h
index 78430ba..5839723 100644
--- a/include/linux/hdlc/ioctl.h
+++ b/include/linux/hdlc/ioctl.h
@@ -1,6 +1,39 @@
 #ifndef __HDLC_IOCTL_H__
 #define __HDLC_IOCTL_H__
 
+
+#define GENERIC_HDLC_VERSION 4	/* For synchronization with sethdlc utility */
+
+#define CLOCK_DEFAULT   0	/* Default setting */
+#define CLOCK_EXT	1	/* External TX and RX clock - DTE */
+#define CLOCK_INT	2	/* Internal TX and RX clock - DCE */
+#define CLOCK_TXINT	3	/* Internal TX and external RX clock */
+#define CLOCK_TXFROMRX	4	/* TX clock derived from external RX clock */
+
+
+#define ENCODING_DEFAULT	0 /* Default setting */
+#define ENCODING_NRZ		1
+#define ENCODING_NRZI		2
+#define ENCODING_FM_MARK	3
+#define ENCODING_FM_SPACE	4
+#define ENCODING_MANCHESTER	5
+
+
+#define PARITY_DEFAULT		0 /* Default setting */
+#define PARITY_NONE		1 /* No parity */
+#define PARITY_CRC16_PR0	2 /* CRC16, initial value 0x0000 */
+#define PARITY_CRC16_PR1	3 /* CRC16, initial value 0xFFFF */
+#define PARITY_CRC16_PR0_CCITT	4 /* CRC16, initial 0x0000, ITU-T version */
+#define PARITY_CRC16_PR1_CCITT	5 /* CRC16, initial 0xFFFF, ITU-T version */
+#define PARITY_CRC32_PR0_CCITT	6 /* CRC32, initial value 0x00000000 */
+#define PARITY_CRC32_PR1_CCITT	7 /* CRC32, initial value 0xFFFFFFFF */
+
+#define LMI_DEFAULT		0 /* Default setting */
+#define LMI_NONE		1 /* No LMI, all PVCs are static */
+#define LMI_ANSI		2 /* ANSI Annex D */
+#define LMI_CCITT		3 /* ITU-T Annex A */
+#define LMI_CISCO		4 /* The "original" LMI, aka Gang of Four */
+
 typedef struct { 
 	unsigned int clock_rate; /* bits per second */
 	unsigned int clock_type; /* internal, external, TX-internal etc. */
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 4fc379d..fca9302 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -138,6 +138,7 @@
 			      struct timespec __user *rmtp,
 			      const enum hrtimer_mode mode,
 			      const clockid_t clockid);
+extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
 
 extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
 				 struct task_struct *tsk);
diff --git a/include/linux/icmp.h b/include/linux/icmp.h
index f0b571f..878cfe4 100644
--- a/include/linux/icmp.h
+++ b/include/linux/icmp.h
@@ -68,16 +68,16 @@
 struct icmphdr {
   __u8		type;
   __u8		code;
-  __u16		checksum;
+  __be16	checksum;
   union {
 	struct {
-		__u16	id;
-		__u16	sequence;
+		__be16	id;
+		__be16	sequence;
 	} echo;
-	__u32	gateway;
+	__be32	gateway;
 	struct {
-		__u16	__unused;
-		__u16	mtu;
+		__be16	__unused;
+		__be16	mtu;
 	} frag;
   } un;
 };
diff --git a/include/linux/if.h b/include/linux/if.h
index cd080d7..32bf419 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -59,6 +59,8 @@
 #define IFF_SLAVE_INACTIVE	0x4	/* bonding slave not the curr. active */
 #define IFF_MASTER_8023AD	0x8	/* bonding master, 802.3ad. 	*/
 #define IFF_MASTER_ALB	0x10		/* bonding master, balance-alb.	*/
+#define IFF_BONDING	0x20		/* bonding master or slave	*/
+#define IFF_SLAVE_NEEDARP 0x40		/* need ARPs for validation	*/
 
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
@@ -212,134 +214,4 @@
 #define	ifc_buf	ifc_ifcu.ifcu_buf		/* buffer address	*/
 #define	ifc_req	ifc_ifcu.ifcu_req		/* array of structures	*/
 
-/* The struct should be in sync with struct net_device_stats */
-struct rtnl_link_stats
-{
-	__u32	rx_packets;		/* total packets received	*/
-	__u32	tx_packets;		/* total packets transmitted	*/
-	__u32	rx_bytes;		/* total bytes received 	*/
-	__u32	tx_bytes;		/* total bytes transmitted	*/
-	__u32	rx_errors;		/* bad packets received		*/
-	__u32	tx_errors;		/* packet transmit problems	*/
-	__u32	rx_dropped;		/* no space in linux buffers	*/
-	__u32	tx_dropped;		/* no space available in linux	*/
-	__u32	multicast;		/* multicast packets received	*/
-	__u32	collisions;
-
-	/* detailed rx_errors: */
-	__u32	rx_length_errors;
-	__u32	rx_over_errors;		/* receiver ring buff overflow	*/
-	__u32	rx_crc_errors;		/* recved pkt with crc error	*/
-	__u32	rx_frame_errors;	/* recv'd frame alignment error */
-	__u32	rx_fifo_errors;		/* recv'r fifo overrun		*/
-	__u32	rx_missed_errors;	/* receiver missed packet	*/
-
-	/* detailed tx_errors */
-	__u32	tx_aborted_errors;
-	__u32	tx_carrier_errors;
-	__u32	tx_fifo_errors;
-	__u32	tx_heartbeat_errors;
-	__u32	tx_window_errors;
-
-	/* for cslip etc */
-	__u32	rx_compressed;
-	__u32	tx_compressed;
-};
-
-/* The struct should be in sync with struct ifmap */
-struct rtnl_link_ifmap
-{
-	__u64	mem_start;
-	__u64	mem_end;
-	__u64	base_addr;
-	__u16	irq;
-	__u8	dma;
-	__u8	port;
-};
-
-enum
-{
-	IFLA_UNSPEC,
-	IFLA_ADDRESS,
-	IFLA_BROADCAST,
-	IFLA_IFNAME,
-	IFLA_MTU,
-	IFLA_LINK,
-	IFLA_QDISC,
-	IFLA_STATS,
-	IFLA_COST,
-#define IFLA_COST IFLA_COST
-	IFLA_PRIORITY,
-#define IFLA_PRIORITY IFLA_PRIORITY
-	IFLA_MASTER,
-#define IFLA_MASTER IFLA_MASTER
-	IFLA_WIRELESS,		/* Wireless Extension event - see wireless.h */
-#define IFLA_WIRELESS IFLA_WIRELESS
-	IFLA_PROTINFO,		/* Protocol specific information for a link */
-#define IFLA_PROTINFO IFLA_PROTINFO
-	IFLA_TXQLEN,
-#define IFLA_TXQLEN IFLA_TXQLEN
-	IFLA_MAP,
-#define IFLA_MAP IFLA_MAP
-	IFLA_WEIGHT,
-#define IFLA_WEIGHT IFLA_WEIGHT
-	IFLA_OPERSTATE,
-	IFLA_LINKMODE,
-	__IFLA_MAX
-};
-
-
-#define IFLA_MAX (__IFLA_MAX - 1)
-
-/* ifi_flags.
-
-   IFF_* flags.
-
-   The only change is:
-   IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
-   more not changeable by user. They describe link media
-   characteristics and set by device driver.
-
-   Comments:
-   - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
-   - If neither of these three flags are set;
-     the interface is NBMA.
-
-   - IFF_MULTICAST does not mean anything special:
-   multicasts can be used on all not-NBMA links.
-   IFF_MULTICAST means that this media uses special encapsulation
-   for multicast frames. Apparently, all IFF_POINTOPOINT and
-   IFF_BROADCAST devices are able to use multicasts too.
- */
-
-/* IFLA_LINK.
-   For usual devices it is equal ifi_index.
-   If it is a "virtual interface" (f.e. tunnel), ifi_link
-   can point to real physical interface (f.e. for bandwidth calculations),
-   or maybe 0, what means, that real media is unknown (usual
-   for IPIP tunnels, when route to endpoint is allowed to change)
- */
-
-/* Subtype attributes for IFLA_PROTINFO */
-enum
-{
-	IFLA_INET6_UNSPEC,
-	IFLA_INET6_FLAGS,	/* link flags			*/
-	IFLA_INET6_CONF,	/* sysctl parameters		*/
-	IFLA_INET6_STATS,	/* statistics			*/
-	IFLA_INET6_MCAST,	/* MC things. What of them?	*/
-	IFLA_INET6_CACHEINFO,	/* time values and max reasm size */
-	__IFLA_INET6_MAX
-};
-
-#define IFLA_INET6_MAX	(__IFLA_INET6_MAX - 1)
-
-struct ifla_cacheinfo
-{
-	__u32	max_reasm_len;
-	__u32	tstamp;		/* ipv6InterfaceTable updated timestamp */
-	__u32	reachable_time;
-	__u32	retrans_time;
-};
-
 #endif /* _LINUX_IF_H */
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index a8b1a20..7f57142 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -130,11 +130,11 @@
 
 struct arphdr
 {
-	unsigned short	ar_hrd;		/* format of hardware address	*/
-	unsigned short	ar_pro;		/* format of protocol address	*/
+	__be16		ar_hrd;		/* format of hardware address	*/
+	__be16		ar_pro;		/* format of protocol address	*/
 	unsigned char	ar_hln;		/* length of hardware address	*/
 	unsigned char	ar_pln;		/* length of protocol address	*/
-	unsigned short	ar_op;		/* ARP opcode (command)		*/
+	__be16		ar_op;		/* ARP opcode (command)		*/
 
 #if 0
 	 /*
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
new file mode 100644
index 0000000..e963a07
--- /dev/null
+++ b/include/linux/if_link.h
@@ -0,0 +1,136 @@
+#ifndef _LINUX_IF_LINK_H
+#define _LINUX_IF_LINK_H
+
+#include <linux/netlink.h>
+
+/* The struct should be in sync with struct net_device_stats */
+struct rtnl_link_stats
+{
+	__u32	rx_packets;		/* total packets received	*/
+	__u32	tx_packets;		/* total packets transmitted	*/
+	__u32	rx_bytes;		/* total bytes received 	*/
+	__u32	tx_bytes;		/* total bytes transmitted	*/
+	__u32	rx_errors;		/* bad packets received		*/
+	__u32	tx_errors;		/* packet transmit problems	*/
+	__u32	rx_dropped;		/* no space in linux buffers	*/
+	__u32	tx_dropped;		/* no space available in linux	*/
+	__u32	multicast;		/* multicast packets received	*/
+	__u32	collisions;
+
+	/* detailed rx_errors: */
+	__u32	rx_length_errors;
+	__u32	rx_over_errors;		/* receiver ring buff overflow	*/
+	__u32	rx_crc_errors;		/* recved pkt with crc error	*/
+	__u32	rx_frame_errors;	/* recv'd frame alignment error */
+	__u32	rx_fifo_errors;		/* recv'r fifo overrun		*/
+	__u32	rx_missed_errors;	/* receiver missed packet	*/
+
+	/* detailed tx_errors */
+	__u32	tx_aborted_errors;
+	__u32	tx_carrier_errors;
+	__u32	tx_fifo_errors;
+	__u32	tx_heartbeat_errors;
+	__u32	tx_window_errors;
+
+	/* for cslip etc */
+	__u32	rx_compressed;
+	__u32	tx_compressed;
+};
+
+/* The struct should be in sync with struct ifmap */
+struct rtnl_link_ifmap
+{
+	__u64	mem_start;
+	__u64	mem_end;
+	__u64	base_addr;
+	__u16	irq;
+	__u8	dma;
+	__u8	port;
+};
+
+enum
+{
+	IFLA_UNSPEC,
+	IFLA_ADDRESS,
+	IFLA_BROADCAST,
+	IFLA_IFNAME,
+	IFLA_MTU,
+	IFLA_LINK,
+	IFLA_QDISC,
+	IFLA_STATS,
+	IFLA_COST,
+#define IFLA_COST IFLA_COST
+	IFLA_PRIORITY,
+#define IFLA_PRIORITY IFLA_PRIORITY
+	IFLA_MASTER,
+#define IFLA_MASTER IFLA_MASTER
+	IFLA_WIRELESS,		/* Wireless Extension event - see wireless.h */
+#define IFLA_WIRELESS IFLA_WIRELESS
+	IFLA_PROTINFO,		/* Protocol specific information for a link */
+#define IFLA_PROTINFO IFLA_PROTINFO
+	IFLA_TXQLEN,
+#define IFLA_TXQLEN IFLA_TXQLEN
+	IFLA_MAP,
+#define IFLA_MAP IFLA_MAP
+	IFLA_WEIGHT,
+#define IFLA_WEIGHT IFLA_WEIGHT
+	IFLA_OPERSTATE,
+	IFLA_LINKMODE,
+	__IFLA_MAX
+};
+
+
+#define IFLA_MAX (__IFLA_MAX - 1)
+
+/* ifi_flags.
+
+   IFF_* flags.
+
+   The only change is:
+   IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
+   more not changeable by user. They describe link media
+   characteristics and set by device driver.
+
+   Comments:
+   - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
+   - If neither of these three flags are set;
+     the interface is NBMA.
+
+   - IFF_MULTICAST does not mean anything special:
+   multicasts can be used on all not-NBMA links.
+   IFF_MULTICAST means that this media uses special encapsulation
+   for multicast frames. Apparently, all IFF_POINTOPOINT and
+   IFF_BROADCAST devices are able to use multicasts too.
+ */
+
+/* IFLA_LINK.
+   For usual devices it is equal ifi_index.
+   If it is a "virtual interface" (f.e. tunnel), ifi_link
+   can point to real physical interface (f.e. for bandwidth calculations),
+   or maybe 0, what means, that real media is unknown (usual
+   for IPIP tunnels, when route to endpoint is allowed to change)
+ */
+
+/* Subtype attributes for IFLA_PROTINFO */
+enum
+{
+	IFLA_INET6_UNSPEC,
+	IFLA_INET6_FLAGS,	/* link flags			*/
+	IFLA_INET6_CONF,	/* sysctl parameters		*/
+	IFLA_INET6_STATS,	/* statistics			*/
+	IFLA_INET6_MCAST,	/* MC things. What of them?	*/
+	IFLA_INET6_CACHEINFO,	/* time values and max reasm size */
+	__IFLA_INET6_MAX
+};
+
+#define IFLA_INET6_MAX	(__IFLA_INET6_MAX - 1)
+
+struct ifla_cacheinfo
+{
+	__u32	max_reasm_len;
+	__u32	tstamp;		/* ipv6InterfaceTable updated timestamp */
+	__u32	reachable_time;
+	__u32	retrans_time;
+};
+
+#endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 899c3d4..03f43e2 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -30,8 +30,8 @@
 {
 	__u8 type;
 	__u8 code;		/* For newer IGMP */
-	__u16 csum;
-	__u32 group;
+	__be16 csum;
+	__be32 group;
 };
 
 /* V3 group record types [grec_type] */
@@ -45,25 +45,25 @@
 struct igmpv3_grec {
 	__u8	grec_type;
 	__u8	grec_auxwords;
-	__u16	grec_nsrcs;
-	__u32	grec_mca;
-	__u32	grec_src[0];
+	__be16	grec_nsrcs;
+	__be32	grec_mca;
+	__be32	grec_src[0];
 };
 
 struct igmpv3_report {
 	__u8 type;
 	__u8 resv1;
-	__u16 csum;
-	__u16 resv2;
-	__u16 ngrec;
+	__be16 csum;
+	__be16 resv2;
+	__be16 ngrec;
 	struct igmpv3_grec grec[0];
 };
 
 struct igmpv3_query {
 	__u8 type;
 	__u8 code;
-	__u16 csum;
-	__u32 group;
+	__be16 csum;
+	__be32 group;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
 	__u8 qrv:3,
 	     suppress:1,
@@ -76,8 +76,8 @@
 #error "Please fix <asm/byteorder.h>"
 #endif
 	__u8 qqic;
-	__u16 nsrcs;
-	__u32 srcs[0];
+	__be16 nsrcs;
+	__be32 srcs[0];
 };
 
 #define IGMP_HOST_MEMBERSHIP_QUERY	0x11	/* From RFC1112 */
@@ -136,11 +136,11 @@
 {
 	unsigned int		sl_max;
 	unsigned int		sl_count;
-	__u32			sl_addr[0];
+	__be32			sl_addr[0];
 };
 
 #define IP_SFLSIZE(count)	(sizeof(struct ip_sf_socklist) + \
-	(count) * sizeof(__u32))
+	(count) * sizeof(__be32))
 
 #define IP_SFBLOCK	10	/* allocate this many at once */
 
@@ -159,7 +159,7 @@
 struct ip_sf_list
 {
 	struct ip_sf_list	*sf_next;
-	__u32			sf_inaddr;
+	__be32			sf_inaddr;
 	unsigned long		sf_count[2];	/* include/exclude counts */
 	unsigned char		sf_gsresp;	/* include in g & s response? */
 	unsigned char		sf_oldin;	/* change state */
@@ -197,7 +197,7 @@
 #define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value)
 #define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value)
 
-extern int ip_check_mc(struct in_device *dev, u32 mc_addr, u32 src_addr, u16 proto);
+extern int ip_check_mc(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u16 proto);
 extern int igmp_rcv(struct sk_buff *);
 extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
 extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
@@ -209,13 +209,13 @@
 		struct ip_msfilter __user *optval, int __user *optlen);
 extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
 		struct group_filter __user *optval, int __user *optlen);
-extern int ip_mc_sf_allow(struct sock *sk, u32 local, u32 rmt, int dif);
+extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif);
 extern void ip_mr_init(void);
 extern void ip_mc_init_dev(struct in_device *);
 extern void ip_mc_destroy_dev(struct in_device *);
 extern void ip_mc_up(struct in_device *);
 extern void ip_mc_down(struct in_device *);
-extern void ip_mc_dec_group(struct in_device *in_dev, u32 addr);
-extern void ip_mc_inc_group(struct in_device *in_dev, u32 addr);
+extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
+extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
 #endif
 #endif
diff --git a/include/linux/in.h b/include/linux/in.h
index bcaca83..d79fc75 100644
--- a/include/linux/in.h
+++ b/include/linux/in.h
@@ -123,17 +123,17 @@
 };
 
 struct ip_mreq_source {
-	__u32		imr_multiaddr;
-	__u32		imr_interface;
-	__u32		imr_sourceaddr;
+	__be32		imr_multiaddr;
+	__be32		imr_interface;
+	__be32		imr_sourceaddr;
 };
 
 struct ip_msfilter {
-	__u32		imsf_multiaddr;
-	__u32		imsf_interface;
+	__be32		imsf_multiaddr;
+	__be32		imsf_interface;
 	__u32		imsf_fmode;
 	__u32		imsf_numsrc;
-	__u32		imsf_slist[1];
+	__be32		imsf_slist[1];
 };
 
 #define IP_MSFILTER_SIZE(numsrc) \
diff --git a/include/linux/in6.h b/include/linux/in6.h
index d776829..9be6a47 100644
--- a/include/linux/in6.h
+++ b/include/linux/in6.h
@@ -32,8 +32,8 @@
 	union 
 	{
 		__u8		u6_addr8[16];
-		__u16		u6_addr16[8];
-		__u32		u6_addr32[4];
+		__be16		u6_addr16[8];
+		__be32		u6_addr32[4];
 	} in6_u;
 #define s6_addr			in6_u.u6_addr8
 #define s6_addr16		in6_u.u6_addr16
@@ -53,7 +53,7 @@
 
 struct sockaddr_in6 {
 	unsigned short int	sin6_family;    /* AF_INET6 */
-	__u16			sin6_port;      /* Transport layer port # */
+	__be16			sin6_port;      /* Transport layer port # */
 	__u32			sin6_flowinfo;  /* IPv6 flow information */
 	struct in6_addr		sin6_addr;      /* IPv6 address */
 	__u32			sin6_scope_id;  /* scope id (new in RFC2553) */
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h
index a4606e5..6e8bc54 100644
--- a/include/linux/inet_diag.h
+++ b/include/linux/inet_diag.h
@@ -9,10 +9,10 @@
 
 /* Socket identity */
 struct inet_diag_sockid {
-	__u16	idiag_sport;
-	__u16	idiag_dport;
-	__u32	idiag_src[4];
-	__u32	idiag_dst[4];
+	__be16	idiag_sport;
+	__be16	idiag_dport;
+	__be32	idiag_src[4];
+	__be32	idiag_dst[4];
 	__u32	idiag_if;
 	__u32	idiag_cookie[2];
 #define INET_DIAG_NOCOOKIE (~0U)
@@ -67,7 +67,7 @@
 	__u8	family;
 	__u8	prefix_len;
 	int	port;
-	__u32	addr[0];
+	__be32	addr[0];
 };
 
 /* Base info structure. It contains socket identity (addrs/ports/cookie)
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 92297ff..5a0ab04 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -90,11 +90,11 @@
 	struct in_ifaddr	*ifa_next;
 	struct in_device	*ifa_dev;
 	struct rcu_head		rcu_head;
-	u32			ifa_local;
-	u32			ifa_address;
-	u32			ifa_mask;
-	u32			ifa_broadcast;
-	u32			ifa_anycast;
+	__be32			ifa_local;
+	__be32			ifa_address;
+	__be32			ifa_mask;
+	__be32			ifa_broadcast;
+	__be32			ifa_anycast;
 	unsigned char		ifa_scope;
 	unsigned char		ifa_flags;
 	unsigned char		ifa_prefixlen;
@@ -104,18 +104,18 @@
 extern int register_inetaddr_notifier(struct notifier_block *nb);
 extern int unregister_inetaddr_notifier(struct notifier_block *nb);
 
-extern struct net_device 	*ip_dev_find(u32 addr);
-extern int		inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b);
+extern struct net_device 	*ip_dev_find(__be32 addr);
+extern int		inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
 extern int		devinet_ioctl(unsigned int cmd, void __user *);
 extern void		devinet_init(void);
 extern struct in_device *inetdev_init(struct net_device *dev);
 extern struct in_device	*inetdev_by_index(int);
-extern u32		inet_select_addr(const struct net_device *dev, u32 dst, int scope);
-extern u32		inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope);
-extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask);
+extern __be32		inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
+extern __be32		inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);
+extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask);
 extern void		inet_forward_change(void);
 
-static __inline__ int inet_ifa_match(u32 addr, struct in_ifaddr *ifa)
+static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa)
 {
 	return !((addr^ifa->ifa_address)&ifa->ifa_mask);
 }
@@ -183,7 +183,7 @@
 
 #endif /* __KERNEL__ */
 
-static __inline__ __u32 inet_make_mask(int logmask)
+static __inline__ __be32 inet_make_mask(int logmask)
 {
 	if (logmask)
 		return htonl(~((1<<(32-logmask))-1));
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index d5afee9..1f97e3d 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -123,6 +123,14 @@
 #endif
 }
 
+static inline void disable_irq_nosync_lockdep_irqsave(unsigned int irq, unsigned long *flags)
+{
+	disable_irq_nosync(irq);
+#ifdef CONFIG_LOCKDEP
+	local_irq_save(*flags);
+#endif
+}
+
 static inline void disable_irq_lockdep(unsigned int irq)
 {
 	disable_irq(irq);
@@ -139,6 +147,14 @@
 	enable_irq(irq);
 }
 
+static inline void enable_irq_lockdep_irqrestore(unsigned int irq, unsigned long *flags)
+{
+#ifdef CONFIG_LOCKDEP
+	local_irq_restore(*flags);
+#endif
+	enable_irq(irq);
+}
+
 /* IRQ wakeup (PM) control: */
 extern int set_irq_wake(unsigned int irq, unsigned int on);
 
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 2f46001..6b25d36 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -96,7 +96,7 @@
 	__be16	frag_off;
 	__u8	ttl;
 	__u8	protocol;
-	__u16	check;
+	__be16	check;
 	__be32	saddr;
 	__be32	daddr;
 	/*The options start here. */
@@ -105,22 +105,22 @@
 struct ip_auth_hdr {
 	__u8  nexthdr;
 	__u8  hdrlen;		/* This one is measured in 32 bit units! */
-	__u16 reserved;
-	__u32 spi;
-	__u32 seq_no;		/* Sequence number */
+	__be16 reserved;
+	__be32 spi;
+	__be32 seq_no;		/* Sequence number */
 	__u8  auth_data[0];	/* Variable len but >=4. Mind the 64 bit alignment! */
 };
 
 struct ip_esp_hdr {
-	__u32 spi;
-	__u32 seq_no;		/* Sequence number */
+	__be32 spi;
+	__be32 seq_no;		/* Sequence number */
 	__u8  enc_data[0];	/* Variable len but >=8. Mind the 64 bit alignment! */
 };
 
 struct ip_comp_hdr {
 	__u8 nexthdr;
 	__u8 flags;
-	__u16 cpi;
+	__be16 cpi;
 };
 
 #endif	/* _LINUX_IP_H */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index caca57d..4f435c5 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -99,22 +99,22 @@
 struct ipv6_auth_hdr {
 	__u8  nexthdr;
 	__u8  hdrlen;           /* This one is measured in 32 bit units! */
-	__u16 reserved;
-	__u32 spi;
-	__u32 seq_no;           /* Sequence number */
+	__be16 reserved;
+	__be32 spi;
+	__be32 seq_no;           /* Sequence number */
 	__u8  auth_data[0];     /* Length variable but >=4. Mind the 64 bit alignment! */
 };
 
 struct ipv6_esp_hdr {
-	__u32 spi;
-	__u32 seq_no;           /* Sequence number */
+	__be32 spi;
+	__be32 seq_no;           /* Sequence number */
 	__u8  enc_data[0];      /* Length variable but >=8. Mind the 64 bit alignment! */
 };
 
 struct ipv6_comp_hdr {
 	__u8 nexthdr;
 	__u8 flags;
-	__u16 cpi;
+	__be16 cpi;
 };
 
 /*
@@ -136,7 +136,7 @@
 #endif
 	__u8			flow_lbl[3];
 
-	__u16			payload_len;
+	__be16			payload_len;
 	__u8			nexthdr;
 	__u8			hop_limit;
 
@@ -461,7 +461,7 @@
 
 #define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\
 	(((__sk)->sk_hash == (__hash))				&& \
-	 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))  	&& \
+	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))  	&& \
 	 ((__sk)->sk_family		== AF_INET6)		&& \
 	 ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))	&& \
 	 ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr))	&& \
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index a6d9daa..fe89444 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -977,7 +977,6 @@
 extern int	journal_set_revoke(journal_t *, unsigned long, tid_t);
 extern int	journal_test_revoke(journal_t *, unsigned long, tid_t);
 extern void	journal_clear_revoke(journal_t *);
-extern void	journal_brelse_array(struct buffer_head *b[], int n);
 extern void	journal_switch_revoke_table(journal_t *journal);
 
 /*
diff --git a/include/linux/leds.h b/include/linux/leds.h
index dc23c7c..88afcef 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -12,6 +12,9 @@
 #ifndef __LINUX_LEDS_H_INCLUDED
 #define __LINUX_LEDS_H_INCLUDED
 
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
 struct device;
 struct class_device;
 /*
diff --git a/include/linux/list.h b/include/linux/list.h
index 65a5b5c..a9c9028 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -39,6 +39,7 @@
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
+#ifndef CONFIG_DEBUG_LIST
 static inline void __list_add(struct list_head *new,
 			      struct list_head *prev,
 			      struct list_head *next)
@@ -48,6 +49,11 @@
 	new->prev = prev;
 	prev->next = new;
 }
+#else
+extern void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next);
+#endif
 
 /**
  * list_add - add a new entry
@@ -57,10 +63,15 @@
  * Insert a new entry after the specified head.
  * This is good for implementing stacks.
  */
+#ifndef CONFIG_DEBUG_LIST
 static inline void list_add(struct list_head *new, struct list_head *head)
 {
 	__list_add(new, head, head->next);
 }
+#else
+extern void list_add(struct list_head *new, struct list_head *head);
+#endif
+
 
 /**
  * list_add_tail - add a new entry
@@ -153,12 +164,16 @@
  * Note: list_empty on entry does not return true after this, the entry is
  * in an undefined state.
  */
+#ifndef CONFIG_DEBUG_LIST
 static inline void list_del(struct list_head *entry)
 {
 	__list_del(entry->prev, entry->next);
 	entry->next = LIST_POISON1;
 	entry->prev = LIST_POISON2;
 }
+#else
+extern void list_del(struct list_head *entry);
+#endif
 
 /**
  * list_del_rcu - deletes entry from list without re-initialization
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index c040a8c..1314ca0 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -8,13 +8,13 @@
 #ifndef __LINUX_LOCKDEP_H
 #define __LINUX_LOCKDEP_H
 
+#ifdef CONFIG_LOCKDEP
+
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/debug_locks.h>
 #include <linux/stacktrace.h>
 
-#ifdef CONFIG_LOCKDEP
-
 /*
  * Lock-class usage-state bits:
  */
diff --git a/include/linux/loop.h b/include/linux/loop.h
index e76c761..191a595 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -59,10 +59,9 @@
 	struct bio 		*lo_bio;
 	struct bio		*lo_biotail;
 	int			lo_state;
-	struct completion	lo_done;
-	struct completion	lo_bh_done;
 	struct mutex		lo_ctl_mutex;
-	int			lo_pending;
+	struct task_struct	*lo_thread;
+	wait_queue_head_t	lo_event;
 
 	request_queue_t		*lo_queue;
 };
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index ba095ae..587264a 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -85,6 +85,8 @@
 	unsigned long		caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
+#define MMC_CAP_MULTIWRITE	(1 << 1)	/* Can accurately report bytes sent to card on error */
+#define MMC_CAP_BYTEBLOCK	(1 << 2)	/* Can do non-log2 block sizes */
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 627e2c0..a3594df 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -68,7 +68,6 @@
 struct mmc_data {
 	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
 	unsigned int		timeout_clks;	/* data timeout (in clocks) */
-	unsigned int		blksz_bits;	/* data block size */
 	unsigned int		blksz;		/* data block size */
 	unsigned int		blocks;		/* number of blocks */
 	unsigned int		error;		/* data error */
diff --git a/include/linux/module.h b/include/linux/module.h
index d4486cc..2c59917 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -232,17 +232,17 @@
 };
 
 /* Similar stuff for section attributes. */
-#define MODULE_SECT_NAME_LEN 32
 struct module_sect_attr
 {
 	struct module_attribute mattr;
-	char name[MODULE_SECT_NAME_LEN];
+	char *name;
 	unsigned long address;
 };
 
 struct module_sect_attrs
 {
 	struct attribute_group grp;
+	int nsections;
 	struct module_sect_attr attrs[0];
 };
 
diff --git a/include/linux/mroute.h b/include/linux/mroute.h
index e05d54a..7da2cee 100644
--- a/include/linux/mroute.h
+++ b/include/linux/mroute.h
@@ -142,7 +142,7 @@
 	unsigned long	rate_limit;		/* Traffic shaping (NI) 	*/
 	unsigned char	threshold;		/* TTL threshold 		*/
 	unsigned short	flags;			/* Control flags 		*/
-	__u32		local,remote;		/* Addresses(remote for tunnels)*/
+	__be32		local,remote;		/* Addresses(remote for tunnels)*/
 	int		link;			/* Physical interface index	*/
 };
 
@@ -151,8 +151,8 @@
 struct mfc_cache 
 {
 	struct mfc_cache *next;			/* Next entry on cache line 	*/
-	__u32 mfc_mcastgrp;			/* Group the entry belongs to 	*/
-	__u32 mfc_origin;			/* Source of packet 		*/
+	__be32 mfc_mcastgrp;			/* Group the entry belongs to 	*/
+	__be32 mfc_origin;			/* Source of packet 		*/
 	vifi_t mfc_parent;			/* Source interface		*/
 	int mfc_flags;				/* Flags on line		*/
 
@@ -179,9 +179,9 @@
 #define MFC_LINES		64
 
 #ifdef __BIG_ENDIAN
-#define MFC_HASH(a,b)	((((a)>>24)^((b)>>26))&(MFC_LINES-1))
+#define MFC_HASH(a,b)	(((((__force u32)(__be32)a)>>24)^(((__force u32)(__be32)b)>>26))&(MFC_LINES-1))
 #else
-#define MFC_HASH(a,b)	(((a)^((b)>>2))&(MFC_LINES-1))
+#define MFC_HASH(a,b)	((((__force u32)(__be32)a)^(((__force u32)(__be32)b)>>2))&(MFC_LINES-1))
 #endif		
 
 #endif
@@ -213,8 +213,8 @@
 {
 	__u8	type;
 	__u8	reserved;
-	__u16	csum;
-	__u32	flags;
+	__be16	csum;
+	__be32	flags;
 };
 
 extern int pim_rcv_v1(struct sk_buff *);
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index bae62d6..ce6c858 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -204,6 +204,7 @@
 		 unicode_xlate:1, /* create escape sequences for unhandled Unicode */
 		 numtail:1,       /* Does first alias have a numeric '~1' type tail? */
 		 atari:1,         /* Use Atari GEMDOS variation of MS-DOS fs */
+		 flush:1,	  /* write things quickly */
 		 nocase:1;	  /* Does this need case conversion? 0=need case conversion*/
 };
 
@@ -412,6 +413,8 @@
 extern int fat_fill_super(struct super_block *sb, void *data, int silent,
 			struct inode_operations *fs_dir_inode_ops, int isvfat);
 
+extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
+		            struct inode *i2);
 /* fat/misc.c */
 extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
 extern void fat_clusters_flush(struct super_block *sb);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 45511a5..c6470ba 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -54,6 +54,7 @@
 #define LOOKUP_OPEN		(0x0100)
 #define LOOKUP_CREATE		(0x0200)
 #define LOOKUP_ACCESS		(0x0400)
+#define LOOKUP_CHDIR		(0x0800)
 
 extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
 extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *));
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4328912..9264139 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -187,7 +187,7 @@
 {
 	struct hh_cache *hh_next;	/* Next entry			     */
 	atomic_t	hh_refcnt;	/* number of users                   */
-	unsigned short  hh_type;	/* protocol identifier, f.e ETH_P_IP
+	__be16		hh_type;	/* protocol identifier, f.e ETH_P_IP
                                          *  NOTE:  For VLANs, this will be the
                                          *  encapuslated type. --BLG
                                          */
@@ -334,7 +334,6 @@
 
 
 	struct net_device_stats* (*get_stats)(struct net_device *dev);
-	struct iw_statistics*	(*get_wireless_stats)(struct net_device *dev);
 
 	/* List of functions to handle Wireless Extensions (instead of ioctl).
 	 * See <net/iw_handler.h> for details. Jean II */
@@ -1016,7 +1015,8 @@
 }
 
 /* On bonding slaves other than the currently active slave, suppress
- * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast.
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
  */
 static inline int skb_bond_should_drop(struct sk_buff *skb)
 {
@@ -1025,6 +1025,10 @@
 
 	if (master &&
 	    (dev->priv_flags & IFF_SLAVE_INACTIVE)) {
+		if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
+		    skb->protocol == __constant_htons(ETH_P_ARP))
+			return 0;
+
 		if (master->priv_flags & IFF_MASTER_ALB) {
 			if (skb->pkt_type != PACKET_BROADCAST &&
 			    skb->pkt_type != PACKET_MULTICAST)
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 149e87c..44e39b6 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -46,11 +46,11 @@
 	struct arpt_devaddr_info tgt_devaddr;
 
 	/* ARP operation code. */
-	u_int16_t arpop, arpop_mask;
+	__be16 arpop, arpop_mask;
 
 	/* ARP hardware address and protocol address format. */
-	u_int16_t arhrd, arhrd_mask;
-	u_int16_t arpro, arpro_mask;
+	__be16 arhrd, arhrd_mask;
+	__be16 arpro, arpro_mask;
 
 	/* The protocol address length is only accepted if it is 4
 	 * so there is no use in offering a way to do filtering on it.
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 51dbec1..64e8680 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -157,7 +157,7 @@
 	unsigned int flags;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
-	u_int32_t saved_ip;
+	__be32 saved_ip;
 	/* This is the original per-proto part, used to map the
 	 * expected connection the way the recipient expects. */
 	union ip_conntrack_manip_proto saved_proto;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 3cbff73..943cc6a 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -30,7 +30,7 @@
 struct ip_conntrack_expect;
 
 extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
-			 u_int32_t * ip, u_int16_t * port);
+			 __be32 * ip, u_int16_t * port);
 extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
 				     struct ip_conntrack_expect *this);
 extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
@@ -38,11 +38,11 @@
 extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
 				  unsigned char **data, int dataoff,
 				  H245_TransportAddress * addr,
-				  u_int32_t ip, u_int16_t port);
+				  __be32 ip, u_int16_t port);
 extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
 				  unsigned char **data, int dataoff,
 				  TransportAddress * addr,
-				  u_int32_t ip, u_int16_t port);
+				  __be32 ip, u_int16_t port);
 extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
 				 struct ip_conntrack * ct,
 				 enum ip_conntrack_info ctinfo,
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
index 2fdabdb..c228bde 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
@@ -23,13 +23,13 @@
 		__be16 port;
 	} tcp;
 	struct {
-		u_int16_t port;
+		__be16 port;
 	} udp;
 	struct {
-		u_int16_t id;
+		__be16 id;
 	} icmp;
 	struct {
-		u_int16_t port;
+		__be16 port;
 	} sctp;
 	struct {
 		__be16 key;	/* key is 32bit, pptp only uses 16 */
@@ -39,7 +39,7 @@
 /* The manipulable part of the tuple. */
 struct ip_conntrack_manip
 {
-	u_int32_t ip;
+	__be32 ip;
 	union ip_conntrack_manip_proto u;
 };
 
@@ -50,22 +50,22 @@
 
 	/* These are the parts of the tuple which are fixed. */
 	struct {
-		u_int32_t ip;
+		__be32 ip;
 		union {
 			/* Add other protocols here. */
 			u_int16_t all;
 
 			struct {
-				u_int16_t port;
+				__be16 port;
 			} tcp;
 			struct {
-				u_int16_t port;
+				__be16 port;
 			} udp;
 			struct {
 				u_int8_t type, code;
 			} icmp;
 			struct {
-				u_int16_t port;
+				__be16 port;
 			} sctp;
 			struct {
 				__be16 key;	/* key is 32bit, 
diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
index 98f8407..bdf5536 100644
--- a/include/linux/netfilter_ipv4/ip_nat.h
+++ b/include/linux/netfilter_ipv4/ip_nat.h
@@ -33,7 +33,7 @@
 	unsigned int flags;
 
 	/* Inclusive: network order. */
-	u_int32_t min_ip, max_ip;
+	__be32 min_ip, max_ip;
 
 	/* Inclusive: network order */
 	union ip_conntrack_manip_proto min, max;
diff --git a/include/linux/netfilter_ipv4/ip_queue.h b/include/linux/netfilter_ipv4/ip_queue.h
index aa08d68..a03507f 100644
--- a/include/linux/netfilter_ipv4/ip_queue.h
+++ b/include/linux/netfilter_ipv4/ip_queue.h
@@ -26,7 +26,7 @@
 	unsigned int hook;		/* Netfilter hook we rode in on */
 	char indev_name[IFNAMSIZ];	/* Name of incoming interface */
 	char outdev_name[IFNAMSIZ];	/* Name of outgoing interface */
-	unsigned short hw_protocol;	/* Hardware protocol (network order) */
+	__be16 hw_protocol;		/* Hardware protocol (network order) */
 	unsigned short hw_type;		/* Hardware type */
 	unsigned char hw_addrlen;	/* Hardware address length */
 	unsigned char hw_addr[8];	/* Hardware address */
diff --git a/include/linux/netfilter_ipv4/ipt_iprange.h b/include/linux/netfilter_ipv4/ipt_iprange.h
index 3ecb3bd..34ab0fb 100644
--- a/include/linux/netfilter_ipv4/ipt_iprange.h
+++ b/include/linux/netfilter_ipv4/ipt_iprange.h
@@ -8,7 +8,7 @@
 
 struct ipt_iprange {
 	/* Inclusive: network order. */
-	u_int32_t min_ip, max_ip;
+	__be32 min_ip, max_ip;
 };
 
 struct ipt_iprange_info
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index c8f4d2f..e16904e 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -4,6 +4,7 @@
 #ifndef LINUX_NMI_H
 #define LINUX_NMI_H
 
+#include <linux/sched.h>
 #include <asm/irq.h>
 
 /**
@@ -16,7 +17,7 @@
 #ifdef ARCH_HAS_NMI_WATCHDOG
 extern void touch_nmi_watchdog(void);
 #else
-# define touch_nmi_watchdog() do { } while(0)
+# define touch_nmi_watchdog() touch_softlockup_watchdog()
 #endif
 
 #endif
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 9d7921d..4830a3b 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -128,12 +128,11 @@
 
 #define PageUptodate(page)	test_bit(PG_uptodate, &(page)->flags)
 #ifdef CONFIG_S390
-#define SetPageUptodate(_page) \
-	do {								      \
-		struct page *__page = (_page);				      \
-		if (!test_and_set_bit(PG_uptodate, &__page->flags))	      \
-			page_test_and_clear_dirty(_page);		      \
-	} while (0)
+static inline void SetPageUptodate(struct page *page)
+{
+	if (!test_and_set_bit(PG_uptodate, &page->flags))
+		page_test_and_clear_dirty(page);
+}
 #else
 #define SetPageUptodate(page)	set_bit(PG_uptodate, &(page)->flags)
 #endif
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ab032ce..b7e85ff 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -479,6 +479,7 @@
 
 #define PCI_VENDOR_ID_AMD		0x1022
 #define PCI_DEVICE_ID_AMD_K8_NB		0x1100
+#define PCI_DEVICE_ID_AMD_K8_NB_MISC	0x1103
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
@@ -1903,6 +1904,7 @@
 #define PCI_DEVICE_ID_TIGON3_5705_2	0x1654
 #define PCI_DEVICE_ID_TIGON3_5720	0x1658
 #define PCI_DEVICE_ID_TIGON3_5721	0x1659
+#define PCI_DEVICE_ID_TIGON3_5722	0x165a
 #define PCI_DEVICE_ID_TIGON3_5705M	0x165d
 #define PCI_DEVICE_ID_TIGON3_5705M_2	0x165e
 #define PCI_DEVICE_ID_TIGON3_5714	0x1668
@@ -1912,6 +1914,7 @@
 #define PCI_DEVICE_ID_TIGON3_5705F	0x166e
 #define PCI_DEVICE_ID_TIGON3_5754M	0x1672
 #define PCI_DEVICE_ID_TIGON3_5755M	0x1673
+#define PCI_DEVICE_ID_TIGON3_5756	0x1674
 #define PCI_DEVICE_ID_TIGON3_5750	0x1676
 #define PCI_DEVICE_ID_TIGON3_5751	0x1677
 #define PCI_DEVICE_ID_TIGON3_5715	0x1678
@@ -1941,6 +1944,8 @@
 #define PCI_DEVICE_ID_TIGON3_5901	0x170d
 #define PCI_DEVICE_ID_BCM4401B1		0x170c
 #define PCI_DEVICE_ID_TIGON3_5901_2	0x170e
+#define PCI_DEVICE_ID_TIGON3_5906	0x1712
+#define PCI_DEVICE_ID_TIGON3_5906M	0x1713
 #define PCI_DEVICE_ID_BCM4401		0x4401
 #define PCI_DEVICE_ID_BCM4401B0		0x4402
 
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 3835a96..46ec72f 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -74,7 +74,7 @@
 	return 0;
 }
 
-static inline void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask)
+static __always_inline void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask)
 {
 	return kzalloc(size, gfp);
 }
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 95572c4..a7dd38f 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -72,6 +72,7 @@
 	int (*timer_create) (struct k_itimer *timer);
 	int (*nsleep) (const clockid_t which_clock, int flags,
 		       struct timespec *, struct timespec __user *);
+	long (*nsleep_restart) (struct restart_block *restart_block);
 	int (*timer_set) (struct k_itimer * timr, int flags,
 			  struct itimerspec * new_setting,
 			  struct itimerspec * old_setting);
@@ -97,6 +98,7 @@
 int posix_cpu_timer_create(struct k_itimer *timer);
 int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 		     struct timespec *rqtp, struct timespec __user *rmtp);
+long posix_cpu_nsleep_restart(struct restart_block *restart_block);
 int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 			struct itimerspec *new, struct itimerspec *old);
 int posix_cpu_timer_del(struct k_itimer *timer);
@@ -111,4 +113,6 @@
 void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
 			   cputime_t *newval, cputime_t *oldval);
 
+long clock_nanosleep_restart(struct restart_block *restart_block);
+
 #endif
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 8b2749a..eeb1976 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -16,8 +16,8 @@
 #define PTRACE_KILL		   8
 #define PTRACE_SINGLESTEP	   9
 
-#define PTRACE_ATTACH		0x10
-#define PTRACE_DETACH		0x11
+#define PTRACE_ATTACH		  16
+#define PTRACE_DETACH		  17
 
 #define PTRACE_SYSCALL		  24
 
diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h
index 806ec5b..fe00f78 100644
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -56,6 +56,16 @@
 extern int reiserfs_xattr_posix_acl_exit(void);
 extern struct reiserfs_xattr_handler posix_acl_default_handler;
 extern struct reiserfs_xattr_handler posix_acl_access_handler;
+
+static inline void reiserfs_init_acl_access(struct inode *inode)
+{
+	REISERFS_I(inode)->i_acl_access = NULL;
+}
+
+static inline void reiserfs_init_acl_default(struct inode *inode)
+{
+	REISERFS_I(inode)->i_acl_default = NULL;
+}
 #else
 
 #define reiserfs_cache_default_acl(inode) 0
@@ -87,4 +97,11 @@
 	return 0;
 }
 
+static inline void reiserfs_init_acl_access(struct inode *inode)
+{
+}
+
+static inline void reiserfs_init_acl_default(struct inode *inode)
+{
+}
 #endif
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index 149be8d..5b3b297 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -52,10 +52,13 @@
 	 ** flushed */
 	unsigned long i_trans_id;
 	struct reiserfs_journal_list *i_jl;
-
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 	struct posix_acl *i_acl_access;
 	struct posix_acl *i_acl_default;
+#endif
+#ifdef CONFIG_REISERFS_FS_XATTR
 	struct rw_semaphore xattr_sem;
+#endif
 	struct inode vfs_inode;
 };
 
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 5e96103..966c358 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -97,6 +97,11 @@
 	inode->i_flags |= S_PRIVATE;
 }
 
+static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
+{
+	init_rwsem(&REISERFS_I(inode)->xattr_sem);
+}
+
 #else
 
 #define is_reiserfs_priv_object(inode) 0
@@ -129,6 +134,9 @@
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL);	/* to be sure */
 	return 0;
 };
+static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
+{
+}
 #endif
 
 #endif				/* __KERNEL__ */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 9c92dc8..3a18add 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -2,7 +2,7 @@
 #define __LINUX_RTNETLINK_H
 
 #include <linux/netlink.h>
-#include <linux/if.h>
+#include <linux/if_link.h>
 
 /****
  *		Routing/neighbour discovery messages.
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9d4aa7f..a06fc89 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -148,6 +148,7 @@
 #define EXIT_DEAD		32
 /* in tsk->state again */
 #define TASK_NONINTERACTIVE	64
+#define TASK_DEAD		128
 
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
@@ -504,8 +505,8 @@
 #define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
 #define rt_task(p)		rt_prio((p)->prio)
 #define batch_task(p)		(unlikely((p)->policy == SCHED_BATCH))
-#define has_rt_policy(p) \
-	unlikely((p)->policy != SCHED_NORMAL && (p)->policy != SCHED_BATCH)
+#define is_rt_policy(p)		((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
+#define has_rt_policy(p)	unlikely(is_rt_policy((p)->policy))
 
 /*
  * Some day this will be a full-fledged user tracking system..
@@ -784,8 +785,9 @@
 	struct prio_array *array;
 
 	unsigned short ioprio;
+#ifdef CONFIG_BLK_DEV_IO_TRACE
 	unsigned int btrace_seq;
-
+#endif
 	unsigned long sleep_avg;
 	unsigned long long timestamp, last_ran;
 	unsigned long long sched_time; /* sched_clock time spent running */
@@ -886,8 +888,10 @@
 				     - initialized normally by flush_old_exec */
 /* file system info */
 	int link_count, total_link_count;
+#ifdef CONFIG_SYSVIPC
 /* ipc stuff */
 	struct sysv_sem sysvsem;
+#endif
 /* CPU-specific state of this task */
 	struct thread_struct thread;
 /* filesystem information */
@@ -1030,6 +1034,16 @@
 	return p->pids[PIDTYPE_PID].pid != NULL;
 }
 
+/**
+ * is_init - check if a task structure is the first user space
+ *	     task the kernel created.
+ * @p: Task structure to be checked.
+ */
+static inline int is_init(struct task_struct *tsk)
+{
+	return tsk->pid == 1;
+}
+
 extern void free_task(struct task_struct *tsk);
 #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
 
@@ -1048,7 +1062,6 @@
 					/* Not implemented yet, only for 486*/
 #define PF_STARTING	0x00000002	/* being created */
 #define PF_EXITING	0x00000004	/* getting shut down */
-#define PF_DEAD		0x00000008	/* Dead */
 #define PF_FORKNOEXEC	0x00000040	/* forked but didn't exec */
 #define PF_SUPERPRIV	0x00000100	/* used super-user privileges */
 #define PF_DUMPCORE	0x00000200	/* dumped core */
@@ -1193,7 +1206,7 @@
 
 #include <asm/current.h>
 
-extern void do_timer(struct pt_regs *);
+extern void do_timer(unsigned long ticks);
 
 extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state));
 extern int FASTCALL(wake_up_process(struct task_struct * tsk));
diff --git a/include/linux/scx200_gpio.h b/include/linux/scx200_gpio.h
index 90dd069..1a82d30 100644
--- a/include/linux/scx200_gpio.h
+++ b/include/linux/scx200_gpio.h
@@ -4,6 +4,7 @@
 
 extern unsigned scx200_gpio_base;
 extern long scx200_gpio_shadow[2];
+extern struct nsc_gpio_ops scx200_gpio_ops;
 
 #define scx200_gpio_present() (scx200_gpio_base!=0)
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 9f56fb8..9b5fea8 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1595,6 +1595,7 @@
 
 static inline int security_inode_alloc (struct inode *inode)
 {
+	inode->i_security = NULL;
 	return security_ops->inode_alloc_security (inode);
 }
 
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index c057f0b..f3c5189 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -19,6 +19,10 @@
 	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* first blocks */
 	struct list_head	swaplist;	/* chain of maybes on swap */
 	struct inode		vfs_inode;
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	struct posix_acl	*i_acl;
+	struct posix_acl	*i_default_acl;
+#endif
 };
 
 struct shmem_sb_info {
@@ -36,4 +40,24 @@
 	return container_of(inode, struct shmem_inode_info, vfs_inode);
 }
 
+#ifdef CONFIG_TMPFS_POSIX_ACL
+int shmem_permission(struct inode *, int, struct nameidata *);
+int shmem_acl_init(struct inode *, struct inode *);
+void shmem_acl_destroy_inode(struct inode *);
+
+extern struct xattr_handler shmem_xattr_acl_access_handler;
+extern struct xattr_handler shmem_xattr_acl_default_handler;
+
+extern struct generic_acl_operations shmem_acl_ops;
+
+#else
+static inline int shmem_acl_init(struct inode *inode, struct inode *dir)
+{
+	return 0;
+}
+static inline void shmem_acl_destroy_inode(struct inode *inode)
+{
+}
+#endif  /* CONFIG_TMPFS_POSIX_ACL */
+
 #endif
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 31473db..b800d2d 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -167,9 +167,9 @@
  * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
  * methods are defined as nops in the case they are not required.
  */
-#define spin_trylock(lock)		__cond_lock(_spin_trylock(lock))
-#define read_trylock(lock)		__cond_lock(_read_trylock(lock))
-#define write_trylock(lock)		__cond_lock(_write_trylock(lock))
+#define spin_trylock(lock)		__cond_lock(lock, _spin_trylock(lock))
+#define read_trylock(lock)		__cond_lock(lock, _read_trylock(lock))
+#define write_trylock(lock)		__cond_lock(lock, _write_trylock(lock))
 
 #define spin_lock(lock)			_spin_lock(lock)
 
@@ -236,19 +236,19 @@
 					_write_unlock_irqrestore(lock, flags)
 #define write_unlock_bh(lock)		_write_unlock_bh(lock)
 
-#define spin_trylock_bh(lock)		__cond_lock(_spin_trylock_bh(lock))
+#define spin_trylock_bh(lock)	__cond_lock(lock, _spin_trylock_bh(lock))
 
 #define spin_trylock_irq(lock) \
 ({ \
 	local_irq_disable(); \
-	_spin_trylock(lock) ? \
+	spin_trylock(lock) ? \
 	1 : ({ local_irq_enable(); 0;  }); \
 })
 
 #define spin_trylock_irqsave(lock, flags) \
 ({ \
 	local_irq_save(flags); \
-	_spin_trylock(lock) ? \
+	spin_trylock(lock) ? \
 	1 : ({ local_irq_restore(flags); 0; }); \
 })
 
@@ -264,7 +264,7 @@
  */
 extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
 #define atomic_dec_and_lock(atomic, lock) \
-		__cond_lock(_atomic_dec_and_lock(atomic, lock))
+		__cond_lock(lock, _atomic_dec_and_lock(atomic, lock))
 
 /**
  * spin_can_lock - would spin_trylock() succeed?
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
index b2c4f82..8828b81 100644
--- a/include/linux/spinlock_api_smp.h
+++ b/include/linux/spinlock_api_smp.h
@@ -19,41 +19,41 @@
 
 #define assert_spin_locked(x)	BUG_ON(!spin_is_locked(x))
 
-void __lockfunc _spin_lock(spinlock_t *lock)		__acquires(spinlock_t);
+void __lockfunc _spin_lock(spinlock_t *lock)		__acquires(lock);
 void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass)
-							__acquires(spinlock_t);
-void __lockfunc _read_lock(rwlock_t *lock)		__acquires(rwlock_t);
-void __lockfunc _write_lock(rwlock_t *lock)		__acquires(rwlock_t);
-void __lockfunc _spin_lock_bh(spinlock_t *lock)		__acquires(spinlock_t);
-void __lockfunc _read_lock_bh(rwlock_t *lock)		__acquires(rwlock_t);
-void __lockfunc _write_lock_bh(rwlock_t *lock)		__acquires(rwlock_t);
-void __lockfunc _spin_lock_irq(spinlock_t *lock)	__acquires(spinlock_t);
-void __lockfunc _read_lock_irq(rwlock_t *lock)		__acquires(rwlock_t);
-void __lockfunc _write_lock_irq(rwlock_t *lock)		__acquires(rwlock_t);
+							__acquires(lock);
+void __lockfunc _read_lock(rwlock_t *lock)		__acquires(lock);
+void __lockfunc _write_lock(rwlock_t *lock)		__acquires(lock);
+void __lockfunc _spin_lock_bh(spinlock_t *lock)		__acquires(lock);
+void __lockfunc _read_lock_bh(rwlock_t *lock)		__acquires(lock);
+void __lockfunc _write_lock_bh(rwlock_t *lock)		__acquires(lock);
+void __lockfunc _spin_lock_irq(spinlock_t *lock)	__acquires(lock);
+void __lockfunc _read_lock_irq(rwlock_t *lock)		__acquires(lock);
+void __lockfunc _write_lock_irq(rwlock_t *lock)		__acquires(lock);
 unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
-							__acquires(spinlock_t);
+							__acquires(lock);
 unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
-							__acquires(rwlock_t);
+							__acquires(lock);
 unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
-							__acquires(rwlock_t);
+							__acquires(lock);
 int __lockfunc _spin_trylock(spinlock_t *lock);
 int __lockfunc _read_trylock(rwlock_t *lock);
 int __lockfunc _write_trylock(rwlock_t *lock);
 int __lockfunc _spin_trylock_bh(spinlock_t *lock);
-void __lockfunc _spin_unlock(spinlock_t *lock)		__releases(spinlock_t);
-void __lockfunc _read_unlock(rwlock_t *lock)		__releases(rwlock_t);
-void __lockfunc _write_unlock(rwlock_t *lock)		__releases(rwlock_t);
-void __lockfunc _spin_unlock_bh(spinlock_t *lock)	__releases(spinlock_t);
-void __lockfunc _read_unlock_bh(rwlock_t *lock)		__releases(rwlock_t);
-void __lockfunc _write_unlock_bh(rwlock_t *lock)	__releases(rwlock_t);
-void __lockfunc _spin_unlock_irq(spinlock_t *lock)	__releases(spinlock_t);
-void __lockfunc _read_unlock_irq(rwlock_t *lock)	__releases(rwlock_t);
-void __lockfunc _write_unlock_irq(rwlock_t *lock)	__releases(rwlock_t);
+void __lockfunc _spin_unlock(spinlock_t *lock)		__releases(lock);
+void __lockfunc _read_unlock(rwlock_t *lock)		__releases(lock);
+void __lockfunc _write_unlock(rwlock_t *lock)		__releases(lock);
+void __lockfunc _spin_unlock_bh(spinlock_t *lock)	__releases(lock);
+void __lockfunc _read_unlock_bh(rwlock_t *lock)		__releases(lock);
+void __lockfunc _write_unlock_bh(rwlock_t *lock)	__releases(lock);
+void __lockfunc _spin_unlock_irq(spinlock_t *lock)	__releases(lock);
+void __lockfunc _read_unlock_irq(rwlock_t *lock)	__releases(lock);
+void __lockfunc _write_unlock_irq(rwlock_t *lock)	__releases(lock);
 void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
-							__releases(spinlock_t);
+							__releases(lock);
 void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
-							__releases(rwlock_t);
+							__releases(lock);
 void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
-							__releases(rwlock_t);
+							__releases(lock);
 
 #endif /* __LINUX_SPINLOCK_API_SMP_H */
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index a6de332..862c0d8c 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -109,13 +109,13 @@
 	void			(*crdestroy)(struct rpc_cred *);
 
 	int			(*crmatch)(struct auth_cred *, struct rpc_cred *, int);
-	u32 *			(*crmarshal)(struct rpc_task *, u32 *);
+	__be32 *		(*crmarshal)(struct rpc_task *, __be32 *);
 	int			(*crrefresh)(struct rpc_task *);
-	u32 *			(*crvalidate)(struct rpc_task *, u32 *);
+	__be32 *		(*crvalidate)(struct rpc_task *, __be32 *);
 	int			(*crwrap_req)(struct rpc_task *, kxdrproc_t,
-						void *, u32 *, void *);
+						void *, __be32 *, void *);
 	int			(*crunwrap_resp)(struct rpc_task *, kxdrproc_t,
-						void *, u32 *, void *);
+						void *, __be32 *, void *);
 };
 
 extern struct rpc_authops	authunix_ops;
@@ -134,10 +134,10 @@
 void			rpcauth_holdcred(struct rpc_task *);
 void			put_rpccred(struct rpc_cred *);
 void			rpcauth_unbindcred(struct rpc_task *);
-u32 *			rpcauth_marshcred(struct rpc_task *, u32 *);
-u32 *			rpcauth_checkverf(struct rpc_task *, u32 *);
-int			rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, u32 *data, void *obj);
-int			rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, u32 *data, void *obj);
+__be32 *		rpcauth_marshcred(struct rpc_task *, __be32 *);
+__be32 *		rpcauth_checkverf(struct rpc_task *, __be32 *);
+int			rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, __be32 *data, void *obj);
+int			rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, __be32 *data, void *obj);
 int			rpcauth_refreshcred(struct rpc_task *);
 void			rpcauth_invalcred(struct rpc_task *);
 int			rpcauth_uptodatecred(struct rpc_task *);
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h
index f43f237..d9f5934 100644
--- a/include/linux/sunrpc/msg_prot.h
+++ b/include/linux/sunrpc/msg_prot.h
@@ -95,7 +95,7 @@
  * 2GB.
  */
 
-typedef u32	rpc_fraghdr;
+typedef __be32	rpc_fraghdr;
 
 #define	RPC_LAST_STREAM_FRAGMENT	(1U << 31)
 #define	RPC_FRAGMENT_SIZE_MASK		(~RPC_LAST_STREAM_FRAGMENT)
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 7b27c09..73140ee 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -78,28 +78,45 @@
  */
 #define RPCSVC_MAXPAGES		((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 2)
 
-static inline u32 svc_getu32(struct kvec *iov)
+static inline u32 svc_getnl(struct kvec *iov)
 {
-	u32 val, *vp;
+	__be32 val, *vp;
 	vp = iov->iov_base;
 	val = *vp++;
 	iov->iov_base = (void*)vp;
-	iov->iov_len -= sizeof(u32);
+	iov->iov_len -= sizeof(__be32);
+	return ntohl(val);
+}
+
+static inline void svc_putnl(struct kvec *iov, u32 val)
+{
+	__be32 *vp = iov->iov_base + iov->iov_len;
+	*vp = htonl(val);
+	iov->iov_len += sizeof(__be32);
+}
+
+static inline __be32 svc_getu32(struct kvec *iov)
+{
+	__be32 val, *vp;
+	vp = iov->iov_base;
+	val = *vp++;
+	iov->iov_base = (void*)vp;
+	iov->iov_len -= sizeof(__be32);
 	return val;
 }
 
 static inline void svc_ungetu32(struct kvec *iov)
 {
-	u32 *vp = (u32 *)iov->iov_base;
+	__be32 *vp = (__be32 *)iov->iov_base;
 	iov->iov_base = (void *)(vp - 1);
 	iov->iov_len += sizeof(*vp);
 }
 
-static inline void svc_putu32(struct kvec *iov, u32 val)
+static inline void svc_putu32(struct kvec *iov, __be32 val)
 {
-	u32 *vp = iov->iov_base + iov->iov_len;
+	__be32 *vp = iov->iov_base + iov->iov_len;
 	*vp = val;
-	iov->iov_len += sizeof(u32);
+	iov->iov_len += sizeof(__be32);
 }
 
 	
@@ -130,7 +147,7 @@
 	short			rq_arghi;	/* pages available in argument page list */
 	short			rq_resused;	/* pages used for result */
 
-	u32			rq_xid;		/* transmission id */
+	__be32			rq_xid;		/* transmission id */
 	u32			rq_prog;	/* program number */
 	u32			rq_vers;	/* program version */
 	u32			rq_proc;	/* procedure number */
@@ -139,7 +156,7 @@
 				rq_secure  : 1;	/* secure port */
 
 
-	__u32			rq_daddr;	/* dest addr of request - reply from here */
+	__be32			rq_daddr;	/* dest addr of request - reply from here */
 
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
@@ -169,7 +186,7 @@
  * Check buffer bounds after decoding arguments
  */
 static inline int
-xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
+xdr_argsize_check(struct svc_rqst *rqstp, __be32 *p)
 {
 	char *cp = (char *)p;
 	struct kvec *vec = &rqstp->rq_arg.head[0];
@@ -178,7 +195,7 @@
 }
 
 static inline int
-xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
+xdr_ressize_check(struct svc_rqst *rqstp, __be32 *p)
 {
 	struct kvec *vec = &rqstp->rq_res.head[0];
 	char *cp = (char*)p;
@@ -249,10 +266,10 @@
 	u32			prot;	/* protocol (UDP or TCP) */
 	struct sockaddr_in	addr;
 	struct svc_sock		*svsk;	/* where reply must go */
-	u32			daddr;	/* where reply must come from */
+	__be32			daddr;	/* where reply must come from */
 	struct cache_deferred_req handle;
 	int			argslen;
-	u32			args[0];
+	__be32			args[0];
 };
 
 /*
@@ -284,7 +301,7 @@
 	 * A return value of 0 means drop the request. 
 	 * vs_dispatch == NULL means use default dispatcher.
 	 */
-	int			(*vs_dispatch)(struct svc_rqst *, u32 *);
+	int			(*vs_dispatch)(struct svc_rqst *, __be32 *);
 };
 
 /*
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 2fe2087..a660165 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -95,7 +95,7 @@
 	char *	name;
 	struct module *owner;
 	int	flavour;
-	int	(*accept)(struct svc_rqst *rq, u32 *authp);
+	int	(*accept)(struct svc_rqst *rq, __be32 *authp);
 	int	(*release)(struct svc_rqst *rq);
 	void	(*domain_release)(struct auth_domain *);
 	int	(*set_client)(struct svc_rqst *rq);
@@ -112,7 +112,7 @@
 #define	SVC_COMPLETE	9
 
 
-extern int	svc_authenticate(struct svc_rqst *rqstp, u32 *authp);
+extern int	svc_authenticate(struct svc_rqst *rqstp, __be32 *authp);
 extern int	svc_authorise(struct svc_rqst *rqstp);
 extern int	svc_set_client(struct svc_rqst *rqstp);
 extern int	svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index e6d3d34..953723b 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -32,7 +32,7 @@
  * side) or svc_rqst pointer (server side).
  * Encode functions always assume there's enough room in the buffer.
  */
-typedef int	(*kxdrproc_t)(void *rqstp, u32 *data, void *obj);
+typedef int	(*kxdrproc_t)(void *rqstp, __be32 *data, void *obj);
 
 /*
  * Basic structure for transmission/reception of a client XDR message.
@@ -88,19 +88,19 @@
 /*
  * Miscellaneous XDR helper functions
  */
-u32 *	xdr_encode_opaque_fixed(u32 *p, const void *ptr, unsigned int len);
-u32 *	xdr_encode_opaque(u32 *p, const void *ptr, unsigned int len);
-u32 *	xdr_encode_string(u32 *p, const char *s);
-u32 *	xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen);
-u32 *	xdr_encode_netobj(u32 *p, const struct xdr_netobj *);
-u32 *	xdr_decode_netobj(u32 *p, struct xdr_netobj *);
+__be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int len);
+__be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int len);
+__be32 *xdr_encode_string(__be32 *p, const char *s);
+__be32 *xdr_decode_string_inplace(__be32 *p, char **sp, int *lenp, int maxlen);
+__be32 *xdr_encode_netobj(__be32 *p, const struct xdr_netobj *);
+__be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *);
 
 void	xdr_encode_pages(struct xdr_buf *, struct page **, unsigned int,
 			 unsigned int);
 void	xdr_inline_pages(struct xdr_buf *, unsigned int,
 			 struct page **, unsigned int, unsigned int);
 
-static inline u32 *xdr_encode_array(u32 *p, const void *s, unsigned int len)
+static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
 {
 	return xdr_encode_opaque(p, s, len);
 }
@@ -108,16 +108,16 @@
 /*
  * Decode 64bit quantities (NFSv3 support)
  */
-static inline u32 *
-xdr_encode_hyper(u32 *p, __u64 val)
+static inline __be32 *
+xdr_encode_hyper(__be32 *p, __u64 val)
 {
 	*p++ = htonl(val >> 32);
 	*p++ = htonl(val & 0xFFFFFFFF);
 	return p;
 }
 
-static inline u32 *
-xdr_decode_hyper(u32 *p, __u64 *valp)
+static inline __be32 *
+xdr_decode_hyper(__be32 *p, __u64 *valp)
 {
 	*valp  = ((__u64) ntohl(*p++)) << 32;
 	*valp |= ntohl(*p++);
@@ -128,7 +128,7 @@
  * Adjust kvec to reflect end of xdr'ed data (RPC client XDR)
  */
 static inline int
-xdr_adjust_iovec(struct kvec *iov, u32 *p)
+xdr_adjust_iovec(struct kvec *iov, __be32 *p)
 {
 	return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base);
 }
@@ -180,19 +180,19 @@
  * Provide some simple tools for XDR buffer overflow-checking etc.
  */
 struct xdr_stream {
-	uint32_t *p;		/* start of available buffer */
+	__be32 *p;		/* start of available buffer */
 	struct xdr_buf *buf;	/* XDR buffer to read/write */
 
-	uint32_t *end;		/* end of available buffer space */
+	__be32 *end;		/* end of available buffer space */
 	struct kvec *iov;	/* pointer to the current kvec */
 };
 
-extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p);
-extern uint32_t *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
+extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
+extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
 		unsigned int base, unsigned int len);
-extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p);
-extern uint32_t *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
+extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
+extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
 
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index bdeba85..6cf6265 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -79,7 +79,7 @@
 	 * This is the private part
 	 */
 	struct rpc_task *	rq_task;	/* RPC task data */
-	__u32			rq_xid;		/* request XID */
+	__be32			rq_xid;		/* request XID */
 	int			rq_cong;	/* has incremented xprt->cong */
 	int			rq_received;	/* receive completed */
 	u32			rq_seqno;	/* gss seq no. used on req. */
@@ -171,9 +171,9 @@
 	/*
 	 * State of TCP reply receive stuff
 	 */
-	u32			tcp_recm,	/* Fragment header */
-				tcp_xid,	/* Current XID */
-				tcp_reclen,	/* fragment length */
+	__be32			tcp_recm,	/* Fragment header */
+				tcp_xid;	/* Current XID */
+	u32			tcp_reclen,	/* fragment length */
 				tcp_offset;	/* fragment offset */
 	unsigned long		tcp_copied,	/* copied to request */
 				tcp_flags;
@@ -253,7 +253,7 @@
 struct rpc_xprt *	xprt_get(struct rpc_xprt *xprt);
 void			xprt_put(struct rpc_xprt *xprt);
 
-static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
+static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p)
 {
 	return p + xprt->tsh_size;
 }
@@ -268,7 +268,7 @@
 void			xprt_write_space(struct rpc_xprt *xprt);
 void			xprt_update_rtt(struct rpc_task *task);
 void			xprt_adjust_cwnd(struct rpc_task *task, int result);
-struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
+struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid);
 void			xprt_complete_rqst(struct rpc_task *task, int copied);
 void			xprt_release_rqst_cong(struct rpc_task *task);
 void			xprt_disconnect(struct rpc_xprt *xprt);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3f0f716..2d1c3d5c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -597,6 +597,6 @@
 				    size_t __user *len_ptr);
 asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
 				    size_t len);
-asmlinkage long sys_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache);
+asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
 
 #endif
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 8ebf497..0e058a2 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -21,10 +21,10 @@
 #include <asm/byteorder.h>
 
 struct tcphdr {
-	__u16	source;
-	__u16	dest;
-	__u32	seq;
-	__u32	ack_seq;
+	__be16	source;
+	__be16	dest;
+	__be32	seq;
+	__be32	ack_seq;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
 	__u16	res1:4,
 		doff:4,
@@ -50,9 +50,9 @@
 #else
 #error	"Adjust your <asm/byteorder.h> defines"
 #endif	
-	__u16	window;
-	__u16	check;
-	__u16	urg_ptr;
+	__be16	window;
+	__be16	check;
+	__be16	urg_ptr;
 };
 
 /*
@@ -62,7 +62,7 @@
  */
 union tcp_word_hdr { 
 	struct tcphdr hdr;
-	__u32 		  words[5];
+	__be32 		  words[5];
 }; 
 
 #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
@@ -166,6 +166,11 @@
 #include <net/inet_timewait_sock.h>
 
 /* This defines a selective acknowledgement block. */
+struct tcp_sack_block_wire {
+	__be32	start_seq;
+	__be32	end_seq;
+};
+
 struct tcp_sack_block {
 	__u32	start_seq;
 	__u32	end_seq;
@@ -211,7 +216,7 @@
  *	Header prediction flags
  *	0x5?10 << 16 + snd_wnd in net byte order
  */
-	__u32	pred_flags;
+	__be32	pred_flags;
 
 /*
  *	RFC793 variables by their proper names. This means you can
diff --git a/include/linux/trdevice.h b/include/linux/trdevice.h
index 99e02ef..bfc84a7 100644
--- a/include/linux/trdevice.h
+++ b/include/linux/trdevice.h
@@ -28,7 +28,7 @@
 #include <linux/if_tr.h>
 
 #ifdef __KERNEL__
-extern unsigned short	tr_type_trans(struct sk_buff *skb, struct net_device *dev);
+extern __be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev);
 extern void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct net_device *dev);
 extern struct net_device *alloc_trdev(int sizeof_priv);
 
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 04827ca..ea4c260 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -174,7 +174,7 @@
 	struct tty_driver *driver;
 	int index;
 	struct tty_ldisc ldisc;
-	struct semaphore termios_sem;
+	struct mutex termios_mutex;
 	struct termios *termios, *termios_locked;
 	char name[64];
 	int pgrp;
@@ -190,7 +190,6 @@
 	struct tty_struct *link;
 	struct fasync_struct *fasync;
 	struct tty_bufhead buf;
-	int max_flip_cnt;
 	int alt_speed;		/* For magic substitution of 38400 bps */
 	wait_queue_head_t write_wait;
 	wait_queue_head_t read_wait;
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 90223f0..014b41d 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -20,10 +20,10 @@
 #include <linux/types.h>
 
 struct udphdr {
-	__u16	source;
-	__u16	dest;
-	__u16	len;
-	__u16	check;
+	__be16	source;
+	__be16	dest;
+	__be16	len;
+	__be16	check;
 };
 
 /* UDP socket options */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d2bd0c8..190cc1b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -19,6 +19,7 @@
 #include <linux/fs.h>		/* for struct file_operations */
 #include <linux/completion.h>	/* for struct completion */
 #include <linux/sched.h>	/* for current && schedule_timeout */
+#include <linux/mutex.h>	/* for struct mutex */
 
 struct usb_device;
 struct usb_driver;
@@ -102,8 +103,13 @@
  *	number from the USB core by calling usb_register_dev().
  * @condition: binding state of the interface: not bound, binding
  *	(in probe()), bound to a driver, or unbinding (in disconnect())
+ * @is_active: flag set when the interface is bound and not suspended.
+ * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
+ *	capability during autosuspend.
  * @dev: driver model's view of this device
  * @class_dev: driver model's class view of this device.
+ * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not
+ *	allowed unless the counter is 0.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -142,8 +148,12 @@
 	int minor;			/* minor number this interface is
 					 * bound to */
 	enum usb_interface_condition condition;		/* state of binding */
+	unsigned is_active:1;		/* the interface is not suspended */
+	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+
 	struct device dev;		/* interface specific device info */
 	struct class_device *class_dev;
+	int pm_usage_cnt;		/* usage counter for autosuspend */
 };
 #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define	interface_to_usbdev(intf) \
@@ -254,8 +264,6 @@
 
 /* ----------------------------------------------------------------------- */
 
-struct usb_operations;
-
 /* USB device number allocation bitmap */
 struct usb_devmap {
 	unsigned long devicemap[128 / (8*sizeof(unsigned long))];
@@ -268,6 +276,7 @@
 	struct device *controller;	/* host/master side hardware */
 	int busnum;			/* Bus number (in order of reg) */
 	char *bus_name;			/* stable id (PCI slot_name etc) */
+	u8 uses_dma;			/* Does the host controller use DMA? */
 	u8 otg_port;			/* 0, or number of OTG/HNP port */
 	unsigned is_b_host:1;		/* true during some HNP roleswitches */
 	unsigned b_hnp_enable:1;	/* OTG: did A-Host enable HNP? */
@@ -276,10 +285,8 @@
 					 * round-robin allocation */
 
 	struct usb_devmap devmap;	/* device address allocation map */
-	struct usb_operations *op;	/* Operations (specific to the HC) */
 	struct usb_device *root_hub;	/* Root hub */
 	struct list_head bus_list;	/* list of busses */
-	void *hcpriv;                   /* Host Controller private data */
 
 	int bandwidth_allocated;	/* on this bus: how much of the time
 					 * reserved for periodic (intr/iso)
@@ -294,8 +301,6 @@
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
 
 	struct class_device *class_dev;	/* class device for this bus */
-	struct kref kref;		/* reference counting for this bus */
-	void (*release)(struct usb_bus *bus);
 
 #if defined(CONFIG_USB_MON)
 	struct mon_bus *mon_bus;	/* non-null when associated */
@@ -350,6 +355,7 @@
 
 	unsigned short bus_mA;		/* Current available from the bus */
 	u8 portnum;			/* Parent port number (origin 1) */
+	u8 level;			/* Number of USB hub ancestors */
 
 	int have_langid;		/* whether string_langid is valid */
 	int string_langid;		/* language ID for strings */
@@ -373,6 +379,15 @@
 
 	int maxchild;			/* Number of ports if hub */
 	struct usb_device *children[USB_MAXCHILDREN];
+
+	int pm_usage_cnt;		/* usage counter for autosuspend */
+#ifdef CONFIG_PM
+	struct work_struct autosuspend;	/* for delayed autosuspends */
+	struct mutex pm_mutex;		/* protects PM operations */
+
+	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
+#endif
 };
 #define	to_usb_device(d) container_of(d, struct usb_device, dev)
 
@@ -384,7 +399,7 @@
 #define usb_unlock_device(udev)		up(&(udev)->dev.sem)
 #define usb_trylock_device(udev)	down_trylock(&(udev)->dev.sem)
 extern int usb_lock_device_for_reset(struct usb_device *udev,
-		struct usb_interface *iface);
+				     const struct usb_interface *iface);
 
 /* USB port reset for device reinitialization */
 extern int usb_reset_device(struct usb_device *dev);
@@ -393,6 +408,17 @@
 
 extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
 
+/* USB autosuspend and autoresume */
+#ifdef CONFIG_USB_SUSPEND
+extern int usb_autopm_get_interface(struct usb_interface *intf);
+extern void usb_autopm_put_interface(struct usb_interface *intf);
+
+#else
+#define usb_autopm_get_interface(intf)		0
+#define usb_autopm_put_interface(intf)		do {} while (0)
+#endif
+
+
 /*-------------------------------------------------------------------------*/
 
 /* for drivers using iso endpoints */
@@ -423,10 +449,10 @@
 
 extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
 		int minor);
-extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev,
+extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
 		unsigned ifnum);
 extern struct usb_host_interface *usb_altnum_to_altsetting(
-		struct usb_interface *intf, unsigned int altnum);
+		const struct usb_interface *intf, unsigned int altnum);
 
 
 /**
@@ -464,6 +490,20 @@
 
 /*-------------------------------------------------------------------------*/
 
+extern int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd);
+
+/*-------------------------------------------------------------------------*/
+
 #define USB_DEVICE_ID_MATCH_DEVICE \
 		(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
 #define USB_DEVICE_ID_MATCH_DEV_RANGE \
@@ -540,7 +580,17 @@
 };
 
 /**
- * struct usb_driver - identifies USB driver to usbcore
+ * struct usbdrv_wrap - wrapper for driver-model structure
+ * @driver: The driver-model core driver structure.
+ * @for_devices: Non-zero for device drivers, 0 for interface drivers.
+ */
+struct usbdrv_wrap {
+	struct device_driver driver;
+	int for_devices;
+};
+
+/**
+ * struct usb_driver - identifies USB interface driver to usbcore
  * @name: The driver name should be unique among USB drivers,
  *	and should normally be the same as the module name.
  * @probe: Called to see if the driver is willing to manage a particular
@@ -567,12 +617,14 @@
  *	or your driver's probe function will never get called.
  * @dynids: used internally to hold the list of dynamically added device
  *	ids for this driver.
- * @driver: the driver model core driver structure.
+ * @drvwrap: Driver-model core structure wrapper.
  * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be
  *	added to this driver by preventing the sysfs file from being created.
+ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
+ *	for interfaces bound to this driver.
  *
- * USB drivers must provide a name, probe() and disconnect() methods,
- * and an id_table.  Other driver fields are optional.
+ * USB interface drivers must provide a name, probe() and disconnect()
+ * methods, and an id_table.  Other driver fields are optional.
  *
  * The id_table is used in hotplugging.  It holds a set of descriptors,
  * and specialized data may be associated with each entry.  That table
@@ -606,10 +658,44 @@
 	const struct usb_device_id *id_table;
 
 	struct usb_dynids dynids;
-	struct device_driver driver;
+	struct usbdrv_wrap drvwrap;
 	unsigned int no_dynamic_id:1;
+	unsigned int supports_autosuspend:1;
 };
-#define	to_usb_driver(d) container_of(d, struct usb_driver, driver)
+#define	to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
+
+/**
+ * struct usb_device_driver - identifies USB device driver to usbcore
+ * @name: The driver name should be unique among USB drivers,
+ *	and should normally be the same as the module name.
+ * @probe: Called to see if the driver is willing to manage a particular
+ *	device.  If it is, probe returns zero and uses dev_set_drvdata()
+ *	to associate driver-specific data with the device.  If unwilling
+ *	to manage the device, return a negative errno value.
+ * @disconnect: Called when the device is no longer accessible, usually
+ *	because it has been (or is being) disconnected or the driver's
+ *	module is being unloaded.
+ * @suspend: Called when the device is going to be suspended by the system.
+ * @resume: Called when the device is being resumed by the system.
+ * @drvwrap: Driver-model core structure wrapper.
+ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
+ *	for devices bound to this driver.
+ *
+ * USB drivers must provide all the fields listed above except drvwrap.
+ */
+struct usb_device_driver {
+	const char *name;
+
+	int (*probe) (struct usb_device *udev);
+	void (*disconnect) (struct usb_device *udev);
+
+	int (*suspend) (struct usb_device *udev, pm_message_t message);
+	int (*resume) (struct usb_device *udev);
+	struct usbdrv_wrap drvwrap;
+	unsigned int supports_autosuspend:1;
+};
+#define	to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
+		drvwrap.driver)
 
 extern struct bus_type usb_bus_type;
 
@@ -633,13 +719,17 @@
  * use these in module_init()/module_exit()
  * and don't forget MODULE_DEVICE_TABLE(usb, ...)
  */
-int usb_register_driver(struct usb_driver *, struct module *);
+extern int usb_register_driver(struct usb_driver *, struct module *);
 static inline int usb_register(struct usb_driver *driver)
 {
 	return usb_register_driver(driver, THIS_MODULE);
 }
 extern void usb_deregister(struct usb_driver *);
 
+extern int usb_register_device_driver(struct usb_device_driver *,
+			struct module *);
+extern void usb_deregister_device_driver(struct usb_device_driver *);
+
 extern int usb_register_dev(struct usb_interface *intf,
 			    struct usb_class_driver *class_driver);
 extern void usb_deregister_dev(struct usb_interface *intf,
@@ -885,7 +975,7 @@
  * @setup_packet: pointer to the setup_packet buffer
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  *
  * Initializes a control urb with the proper information needed to submit
@@ -897,7 +987,7 @@
 					 unsigned char *setup_packet,
 					 void *transfer_buffer,
 					 int buffer_length,
-					 usb_complete_t complete,
+					 usb_complete_t complete_fn,
 					 void *context)
 {
 	spin_lock_init(&urb->lock);
@@ -906,7 +996,7 @@
 	urb->setup_packet = setup_packet;
 	urb->transfer_buffer = transfer_buffer;
 	urb->transfer_buffer_length = buffer_length;
-	urb->complete = complete;
+	urb->complete = complete_fn;
 	urb->context = context;
 }
 
@@ -917,7 +1007,7 @@
  * @pipe: the endpoint pipe
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  *
  * Initializes a bulk urb with the proper information needed to submit it
@@ -928,7 +1018,7 @@
 				      unsigned int pipe,
 				      void *transfer_buffer,
 				      int buffer_length,
-				      usb_complete_t complete,
+				      usb_complete_t complete_fn,
 				      void *context)
 {
 	spin_lock_init(&urb->lock);
@@ -936,7 +1026,7 @@
 	urb->pipe = pipe;
 	urb->transfer_buffer = transfer_buffer;
 	urb->transfer_buffer_length = buffer_length;
-	urb->complete = complete;
+	urb->complete = complete_fn;
 	urb->context = context;
 }
 
@@ -947,7 +1037,7 @@
  * @pipe: the endpoint pipe
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  * @interval: what to set the urb interval to, encoded like
  *	the endpoint descriptor's bInterval value.
@@ -963,7 +1053,7 @@
 				     unsigned int pipe,
 				     void *transfer_buffer,
 				     int buffer_length,
-				     usb_complete_t complete,
+				     usb_complete_t complete_fn,
 				     void *context,
 				     int interval)
 {
@@ -972,7 +1062,7 @@
 	urb->pipe = pipe;
 	urb->transfer_buffer = transfer_buffer;
 	urb->transfer_buffer_length = buffer_length;
-	urb->complete = complete;
+	urb->complete = complete_fn;
 	urb->context = context;
 	if (dev->speed == USB_SPEED_HIGH)
 		urb->interval = 1 << (interval - 1);
@@ -990,7 +1080,6 @@
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
 
-#define HAVE_USB_BUFFERS
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
 	gfp_t mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
@@ -1003,14 +1092,14 @@
 #endif
 
 struct scatterlist;
-int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
-		struct scatterlist *sg, int nents);
+int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+		      struct scatterlist *sg, int nents);
 #if 0
-void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
-		struct scatterlist *sg, int n_hw_ents);
+void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
+			   struct scatterlist *sg, int n_hw_ents);
 #endif
-void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
-		struct scatterlist *sg, int n_hw_ents);
+void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
+			 struct scatterlist *sg, int n_hw_ents);
 
 /*-------------------------------------------------------------------*
  *                         SYNCHRONOUS CALL SUPPORT                  *
@@ -1038,6 +1127,9 @@
 extern int usb_reset_configuration(struct usb_device *dev);
 extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
 
+/* this request isn't really synchronous, but it belongs with the others */
+extern int usb_driver_set_configuration(struct usb_device *udev, int config);
+
 /*
  * timeouts, in milliseconds, used for sending/receiving control messages
  * they typically complete within a few frames (msec) after they're issued
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
new file mode 100644
index 0000000..6bd2359
--- /dev/null
+++ b/include/linux/usb/audio.h
@@ -0,0 +1,53 @@
+/*
+ * <linux/usb/audio.h> -- USB Audio definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for Audio Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/audio10.pdf
+ */
+
+#ifndef __LINUX_USB_AUDIO_H
+#define __LINUX_USB_AUDIO_H
+
+#include <linux/types.h>
+
+/* A.2 Audio Interface Subclass Codes */
+#define USB_SUBCLASS_AUDIOCONTROL	0x01
+#define USB_SUBCLASS_AUDIOSTREAMING	0x02
+#define USB_SUBCLASS_MIDISTREAMING	0x03
+
+/* 4.3.2  Class-Specific AC Interface Descriptor */
+struct usb_ac_header_descriptor {
+	__u8  bLength;			// 8+n
+	__u8  bDescriptorType;		// USB_DT_CS_INTERFACE
+	__u8  bDescriptorSubtype;	// USB_MS_HEADER
+	__le16 bcdADC;			// 0x0100
+	__le16 wTotalLength;		// includes Unit and Terminal desc.
+	__u8  bInCollection;		// n
+	__u8  baInterfaceNr[];		// [n]
+} __attribute__ ((packed));
+
+#define USB_DT_AC_HEADER_SIZE(n)	(8+(n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_AC_HEADER_DESCRIPTOR(n) 			\
+struct usb_ac_header_descriptor_##n {				\
+	__u8  bLength;						\
+	__u8  bDescriptorType;					\
+	__u8  bDescriptorSubtype;				\
+	__le16 bcdADC;						\
+	__le16 wTotalLength;					\
+	__u8  bInCollection;					\
+	__u8  baInterfaceNr[n];					\
+} __attribute__ ((packed))
+
+#endif
diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
new file mode 100644
index 0000000..11a97d5
--- /dev/null
+++ b/include/linux/usb/midi.h
@@ -0,0 +1,112 @@
+/*
+ * <linux/usb/midi.h> -- USB MIDI definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for MIDI Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ */
+
+#ifndef __LINUX_USB_MIDI_H
+#define __LINUX_USB_MIDI_H
+
+#include <linux/types.h>
+
+/* A.1  MS Class-Specific Interface Descriptor Subtypes */
+#define USB_MS_HEADER		0x01
+#define USB_MS_MIDI_IN_JACK	0x02
+#define USB_MS_MIDI_OUT_JACK	0x03
+#define USB_MS_ELEMENT		0x04
+
+/* A.2  MS Class-Specific Endpoint Descriptor Subtypes */
+#define USB_MS_GENERAL		0x01
+
+/* A.3  MS MIDI IN and OUT Jack Types */
+#define USB_MS_EMBEDDED		0x01
+#define USB_MS_EXTERNAL		0x02
+
+/* 6.1.2.1  Class-Specific MS Interface Header Descriptor */
+struct usb_ms_header_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bDescriptorSubtype;
+	__le16 bcdMSC;
+	__le16 wTotalLength;
+} __attribute__ ((packed));
+
+#define USB_DT_MS_HEADER_SIZE	7
+
+/* 6.1.2.2  MIDI IN Jack Descriptor */
+struct usb_midi_in_jack_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;		// USB_DT_CS_INTERFACE
+	__u8  bDescriptorSubtype;	// USB_MS_MIDI_IN_JACK
+	__u8  bJackType;		// USB_MS_EMBEDDED/EXTERNAL
+	__u8  bJackID;
+	__u8  iJack;
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_IN_SIZE	6
+
+struct usb_midi_source_pin {
+	__u8  baSourceID;
+	__u8  baSourcePin;
+} __attribute__ ((packed));
+
+/* 6.1.2.3  MIDI OUT Jack Descriptor */
+struct usb_midi_out_jack_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;		// USB_DT_CS_INTERFACE
+	__u8  bDescriptorSubtype;	// USB_MS_MIDI_OUT_JACK
+	__u8  bJackType;		// USB_MS_EMBEDDED/EXTERNAL
+	__u8  bJackID;
+	__u8  bNrInputPins;		// p
+	struct usb_midi_source_pin pins[]; // [p]
+	/*__u8  iJack;  -- ommitted due to variable-sized pins[] */
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_OUT_SIZE(p)	(7 + 2 * (p))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(p)			\
+struct usb_midi_out_jack_descriptor_##p {			\
+	__u8  bLength;						\
+	__u8  bDescriptorType;					\
+	__u8  bDescriptorSubtype;				\
+	__u8  bJackType;					\
+	__u8  bJackID;						\
+	__u8  bNrInputPins;					\
+	struct usb_midi_source_pin pins[p];			\
+	__u8  iJack;						\
+} __attribute__ ((packed))
+
+/* 6.2.2  Class-Specific MS Bulk Data Endpoint Descriptor */
+struct usb_ms_endpoint_descriptor {
+	__u8  bLength;			// 4+n
+	__u8  bDescriptorType;		// USB_DT_CS_ENDPOINT
+	__u8  bDescriptorSubtype;	// USB_MS_GENERAL
+	__u8  bNumEmbMIDIJack;		// n
+	__u8  baAssocJackID[];		// [n]
+} __attribute__ ((packed));
+
+#define USB_DT_MS_ENDPOINT_SIZE(n)	(4 + (n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(n)			\
+struct usb_ms_endpoint_descriptor_##n {				\
+	__u8  bLength;						\
+	__u8  bDescriptorType;					\
+	__u8  bDescriptorSubtype;				\
+	__u8  bNumEmbMIDIJack;					\
+	__u8  baAssocJackID[n];					\
+} __attribute__ ((packed))
+
+#endif
diff --git a/include/linux/usb_otg.h b/include/linux/usb/otg.h
similarity index 97%
rename from include/linux/usb_otg.h
rename to include/linux/usb/otg.h
index f827f6e..9897f7a 100644
--- a/include/linux/usb_otg.h
+++ b/include/linux/usb/otg.h
@@ -1,4 +1,4 @@
-// include/linux/usb_otg.h 
+// include/linux/usb/otg.h
 
 /*
  * These APIs may be used between USB controllers.  USB device drivers
@@ -52,7 +52,7 @@
 	u16			port_change;
 
 	/* bind/unbind the host controller */
-	int 	(*set_host)(struct otg_transceiver *otg,
+	int	(*set_host)(struct otg_transceiver *otg,
 				struct usb_bus *host);
 
 	/* bind/unbind the peripheral controller */
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index e7fc5fe..2ae76fe 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -108,6 +108,9 @@
 #ifdef CONFIG_USB_STORAGE_ALAUDA
 #define US_PR_ALAUDA    0xf4		/* Alauda chipsets */
 #endif
+#ifdef CONFIG_USB_STORAGE_KARMA
+#define US_PR_KARMA     0xf5		/* Rio Karma */
+#endif
 
 #define US_PR_DEVICE	0xff		/* Use device's value */
 
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 176c7f7..c89df55 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 #include <linux/percpu.h>
-#include <linux/config.h>
 #include <linux/mmzone.h>
 #include <asm/atomic.h>
 
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 918a297..1009d3f 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -33,7 +33,8 @@
 int vc_allocate(unsigned int console);
 int vc_cons_allocated(unsigned int console);
 int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
-void vc_disallocate(unsigned int console);
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
+void vc_deallocate(unsigned int console);
 void reset_palette(struct vc_data *vc);
 void do_blank_screen(int entering_gfx);
 void do_unblank_screen(int leaving_gfx);
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index 1358856..a50a013 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1,7 +1,7 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :	20	17.2.06
+ * Version :	21	14.3.06
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
@@ -69,9 +69,14 @@
 
 /***************************** INCLUDES *****************************/
 
+/* This header is used in user-space, therefore need to be sanitised
+ * for that purpose. Those includes are usually not compatible with glibc.
+ * To know which includes to use in user-space, check iwlib.h. */
+#ifdef __KERNEL__
 #include <linux/types.h>		/* for "caddr_t" et al		*/
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 #include <linux/if.h>			/* for IFNAMSIZ and co... */
+#endif	/* __KERNEL__ */
 
 /***************************** VERSION *****************************/
 /*
@@ -80,7 +85,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	20
+#define WIRELESS_EXT	21
 
 /*
  * Changes :
@@ -208,6 +213,14 @@
  * V19 to V20
  * ----------
  *	- RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ *	- Remove (struct net_device *)->get_wireless_stats()
+ *	- Change length in ESSID and NICK to strlen() instead of strlen()+1
+ *	- Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ *	- Power/Retry relative values no longer * 100000
+ *	- Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
  */
 
 /**************************** CONSTANTS ****************************/
@@ -448,6 +461,7 @@
 #define IW_QUAL_QUAL_INVALID	0x10	/* Driver doesn't provide value */
 #define IW_QUAL_LEVEL_INVALID	0x20
 #define IW_QUAL_NOISE_INVALID	0x40
+#define IW_QUAL_RCPI		0x80	/* Level + Noise are 802.11k RCPI */
 #define IW_QUAL_ALL_INVALID	0x70
 
 /* Frequency flags */
@@ -500,10 +514,12 @@
 #define IW_RETRY_TYPE		0xF000	/* Type of parameter */
 #define IW_RETRY_LIMIT		0x1000	/* Maximum number of retries*/
 #define IW_RETRY_LIFETIME	0x2000	/* Maximum duration of retries in us */
-#define IW_RETRY_MODIFIER	0x000F	/* Modify a parameter */
+#define IW_RETRY_MODIFIER	0x00FF	/* Modify a parameter */
 #define IW_RETRY_MIN		0x0001	/* Value is a minimum  */
 #define IW_RETRY_MAX		0x0002	/* Value is a maximum */
 #define IW_RETRY_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT		0x0010	/* Value is for short packets  */
+#define IW_RETRY_LONG		0x0020	/* Value is for long packets */
 
 /* Scanning request flags */
 #define IW_SCAN_DEFAULT		0x0000	/* Default scan of the driver */
@@ -1017,7 +1033,7 @@
 	/* Note : this frequency list doesn't need to fit channel numbers,
 	 * because each entry contain its channel index */
 
-	__u32		enc_capa; /* IW_ENC_CAPA_* bit field */
+	__u32		enc_capa;	/* IW_ENC_CAPA_* bit field */
 };
 
 /*
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 56a23a0..9d4074e 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -117,6 +117,7 @@
 int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
 			   loff_t pos, loff_t count);
 void set_page_dirty_balance(struct page *page);
+void writeback_set_ratelimit(void);
 
 /* pdflush.c */
 extern int nr_pdflush_threads;	/* Global so it can be exported to sysctl
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 14ecd19..430afd0 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -12,8 +12,8 @@
  */
 typedef union
 {
-	__u32		a4;
-	__u32		a6[4];
+	__be32		a4;
+	__be32		a6[4];
 } xfrm_address_t;
 
 /* Ident of a specific xfrm_state. It is used on input to lookup
@@ -23,7 +23,7 @@
 struct xfrm_id
 {
 	xfrm_address_t	daddr;
-	__u32		spi;
+	__be32		spi;
 	__u8		proto;
 };
 
@@ -49,10 +49,10 @@
 {
 	xfrm_address_t	daddr;
 	xfrm_address_t	saddr;
-	__u16	dport;
-	__u16	dport_mask;
-	__u16	sport;
-	__u16	sport_mask;
+	__be16	dport;
+	__be16	dport_mask;
+	__be16	sport;
+	__be16	sport_mask;
 	__u16	family;
 	__u8	prefixlen_d;
 	__u8	prefixlen_s;
@@ -281,7 +281,7 @@
 
 struct xfrm_usersa_id {
 	xfrm_address_t			daddr;
-	__u32				spi;
+	__be32				spi;
 	__u16				family;
 	__u8				proto;
 };
diff --git a/include/net/arp.h b/include/net/arp.h
index 643bded..6a3d9a7 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -12,15 +12,15 @@
 extern void	arp_init(void);
 extern int	arp_find(unsigned char *haddr, struct sk_buff *skb);
 extern int	arp_ioctl(unsigned int cmd, void __user *arg);
-extern void     arp_send(int type, int ptype, u32 dest_ip, 
-			 struct net_device *dev, u32 src_ip, 
+extern void     arp_send(int type, int ptype, __be32 dest_ip,
+			 struct net_device *dev, __be32 src_ip,
 			 unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
 extern int	arp_bind_neighbour(struct dst_entry *dst);
 extern int	arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir);
 extern void	arp_ifdown(struct net_device *dev);
 
-extern struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
-				  struct net_device *dev, u32 src_ip,
+extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+				  struct net_device *dev, __be32 src_ip,
 				  unsigned char *dest_hw, unsigned char *src_hw,
 				  unsigned char *target_hw);
 extern void arp_xmit(struct sk_buff *skb);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b2bdb1a..10a3eec 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -44,12 +44,13 @@
 #define HCI_NOTIFY_VOICE_SETTING	3
 
 /* HCI device types */
-#define HCI_VHCI	0
+#define HCI_VIRTUAL	0
 #define HCI_USB		1
 #define HCI_PCCARD	2
 #define HCI_UART	3
 #define HCI_RS232	4
 #define HCI_PCI		5
+#define HCI_SDIO	6
 
 /* HCI device quirks */
 enum {
@@ -296,6 +297,7 @@
 
 /* Link Control */
 #define OGF_LINK_CTL	0x01 
+
 #define OCF_CREATE_CONN		0x0005
 struct hci_cp_create_conn {
 	bdaddr_t bdaddr;
@@ -306,6 +308,11 @@
 	__u8     role_switch;
 } __attribute__ ((packed));
 
+#define OCF_CREATE_CONN_CANCEL	0x0008
+struct hci_cp_create_conn_cancel {
+	bdaddr_t bdaddr;
+} __attribute__ ((packed));
+
 #define OCF_ACCEPT_CONN_REQ	0x0009
 struct hci_cp_accept_conn_req {
 	bdaddr_t bdaddr;
@@ -339,6 +346,8 @@
 
 #define OCF_INQUIRY_CANCEL	0x0002
 
+#define OCF_EXIT_PERIODIC_INQ	0x0004
+
 #define OCF_LINK_KEY_REPLY	0x000B
 struct hci_cp_link_key_reply {
 	bdaddr_t bdaddr;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d84855f..df22efc 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -72,6 +72,9 @@
 	__u8		type;
 	bdaddr_t	bdaddr;
 	__u8		features[8];
+	__u8		hci_ver;
+	__u16		hci_rev;
+	__u16		manufacturer;
 	__u16		voice_setting;
 
 	__u16		pkt_type;
@@ -165,6 +168,10 @@
 	struct timer_list disc_timer;
 	struct timer_list idle_timer;
 
+	struct work_struct work;
+
+	struct device	dev;
+
 	struct hci_dev	*hdev;
 	void		*l2cap_data;
 	void		*sco_data;
@@ -309,10 +316,13 @@
 	if (atomic_dec_and_test(&conn->refcnt)) {
 		unsigned long timeo;
 		if (conn->type == ACL_LINK) {
-			timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
-			if (!conn->out)
-				timeo *= 2;
 			del_timer(&conn->idle_timer);
+			if (conn->state == BT_CONNECTED) {
+				timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
+				if (!conn->out)
+					timeo *= 2;
+			} else
+				timeo = msecs_to_jiffies(10);
 		} else
 			timeo = msecs_to_jiffies(10);
 		mod_timer(&conn->disc_timer, jiffies + timeo);
@@ -412,6 +422,8 @@
 
 int hci_register_sysfs(struct hci_dev *hdev);
 void hci_unregister_sysfs(struct hci_dev *hdev);
+void hci_conn_add_sysfs(struct hci_conn *conn);
+void hci_conn_del_sysfs(struct hci_conn *conn);
 
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev))
 
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index 2d72496c..5d6ae1b 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -128,7 +128,9 @@
 
 #ifdef CONFIG_NETLABEL
 int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
-int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head));
+int cipso_v4_doi_remove(u32 doi,
+			u32 audit_secid,
+			void (*callback) (struct rcu_head * head));
 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
 int cipso_v4_doi_walk(u32 *skip_cnt,
 		     int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
@@ -143,6 +145,7 @@
 }
 
 static inline int cipso_v4_doi_remove(u32 doi,
+				    u32 audit_secid,
 				    void (*callback) (struct rcu_head * head))
 {
 	return 0;
diff --git a/include/net/dst.h b/include/net/dst.h
index a8d825f..e156e38 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -84,7 +84,7 @@
 struct dst_ops
 {
 	unsigned short		family;
-	unsigned short		protocol;
+	__be16			protocol;
 	unsigned		gc_thresh;
 
 	int			(*gc)(void);
diff --git a/include/net/flow.h b/include/net/flow.h
index 3ca210e..ddf5f3c 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -16,8 +16,8 @@
 
 	union {
 		struct {
-			__u32			daddr;
-			__u32			saddr;
+			__be32			daddr;
+			__be32			saddr;
 			__u32			fwmark;
 			__u8			tos;
 			__u8			scope;
@@ -56,8 +56,8 @@
 #define FLOWI_FLAG_MULTIPATHOLDROUTE 0x01
 	union {
 		struct {
-			__u16	sport;
-			__u16	dport;
+			__be16	sport;
+			__be16	dport;
 		} ports;
 
 		struct {
@@ -73,7 +73,7 @@
 			__u8	objname[16]; /* Not zero terminated */
 		} dnports;
 
-		__u32		spi;
+		__be32		spi;
 
 #ifdef CONFIG_IPV6_MIP6
 		struct {
diff --git a/include/net/icmp.h b/include/net/icmp.h
index 05f8ff7..dc09474 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -38,7 +38,7 @@
 struct net_proto_family;
 struct sk_buff;
 
-extern void	icmp_send(struct sk_buff *skb_in,  int type, int code, u32 info);
+extern void	icmp_send(struct sk_buff *skb_in,  int type, int code, __be32 info);
 extern int	icmp_rcv(struct sk_buff *skb);
 extern int	icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 extern void	icmp_init(struct net_proto_family *ops);
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index de4e83b6..0bcf9f2 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -238,9 +238,9 @@
 
 extern struct request_sock *inet_csk_search_req(const struct sock *sk,
 						struct request_sock ***prevp,
-						const __u16 rport,
-						const __u32 raddr,
-						const __u32 laddr);
+						const __be16 rport,
+						const __be32 raddr,
+						const __be32 laddr);
 extern int inet_csk_bind_conflict(const struct sock *sk,
 				  const struct inet_bind_bucket *tb);
 extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index b4491c9..a9eb2ea 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -272,42 +272,56 @@
 }
 
 extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
-					   const u32 daddr,
+					   const __be32 daddr,
 					   const unsigned short hnum,
 					   const int dif);
 
 static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
-						u32 daddr, u16 dport, int dif)
+						__be32 daddr, __be16 dport, int dif)
 {
 	return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif);
 }
 
 /* Socket demux engine toys. */
+/* What happens here is ugly; there's a pair of adjacent fields in
+   struct inet_sock; __be16 dport followed by __u16 num.  We want to
+   search by pair, so we combine the keys into a single 32bit value
+   and compare with 32bit value read from &...->dport.  Let's at least
+   make sure that it's not mixed with anything else...
+   On 64bit targets we combine comparisons with pair of adjacent __be32
+   fields in the same way.
+*/
+typedef __u32 __bitwise __portpair;
 #ifdef __BIG_ENDIAN
 #define INET_COMBINED_PORTS(__sport, __dport) \
-	(((__u32)(__sport) << 16) | (__u32)(__dport))
+	((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport)))
 #else /* __LITTLE_ENDIAN */
 #define INET_COMBINED_PORTS(__sport, __dport) \
-	(((__u32)(__dport) << 16) | (__u32)(__sport))
+	((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport)))
 #endif
 
 #if (BITS_PER_LONG == 64)
+typedef __u64 __bitwise __addrpair;
 #ifdef __BIG_ENDIAN
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
-	const __u64 __name = (((__u64)(__saddr)) << 32) | ((__u64)(__daddr));
+	const __addrpair __name = (__force __addrpair) ( \
+				   (((__force __u64)(__be32)(__saddr)) << 32) | \
+				   ((__force __u64)(__be32)(__daddr)));
 #else /* __LITTLE_ENDIAN */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
-	const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr));
+	const __addrpair __name = (__force __addrpair) ( \
+				   (((__force __u64)(__be32)(__daddr)) << 32) | \
+				   ((__force __u64)(__be32)(__saddr)));
 #endif /* __BIG_ENDIAN */
 #define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
 	(((__sk)->sk_hash == (__hash))				&&	\
-	 ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie))	&&	\
-	 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
+	 ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie))	&&	\
+	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
 	(((__sk)->sk_hash == (__hash))				&&	\
-	 ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&	\
-	 ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
+	 ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&	\
+	 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #else /* 32-bit arch */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
@@ -315,13 +329,13 @@
 	(((__sk)->sk_hash == (__hash))				&&	\
 	 (inet_sk(__sk)->daddr		== (__saddr))		&&	\
 	 (inet_sk(__sk)->rcv_saddr	== (__daddr))		&&	\
-	 ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
+	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif)	\
 	(((__sk)->sk_hash == (__hash))				&&	\
 	 (inet_twsk(__sk)->tw_daddr	== (__saddr))		&&	\
 	 (inet_twsk(__sk)->tw_rcv_saddr	== (__daddr))		&&	\
-	 ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
+	 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #endif /* 64-bit arch */
 
@@ -333,12 +347,12 @@
  */
 static inline struct sock *
 	__inet_lookup_established(struct inet_hashinfo *hashinfo,
-				  const u32 saddr, const u16 sport,
-				  const u32 daddr, const u16 hnum,
+				  const __be32 saddr, const __be16 sport,
+				  const __be32 daddr, const u16 hnum,
 				  const int dif)
 {
 	INET_ADDR_COOKIE(acookie, saddr, daddr)
-	const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+	const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
 	struct sock *sk;
 	const struct hlist_node *node;
 	/* Optimize here for direct hit, only listening connections can
@@ -370,8 +384,8 @@
 
 static inline struct sock *
 	inet_lookup_established(struct inet_hashinfo *hashinfo,
-				const u32 saddr, const u16 sport,
-				const u32 daddr, const u16 dport,
+				const __be32 saddr, const __be16 sport,
+				const __be32 daddr, const __be16 dport,
 				const int dif)
 {
 	return __inet_lookup_established(hashinfo, saddr, sport, daddr,
@@ -379,8 +393,8 @@
 }
 
 static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
-					 const u32 saddr, const u16 sport,
-					 const u32 daddr, const u16 dport,
+					 const __be32 saddr, const __be16 sport,
+					 const __be32 daddr, const __be16 dport,
 					 const int dif)
 {
 	u16 hnum = ntohs(dport);
@@ -390,8 +404,8 @@
 }
 
 static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
-				       const u32 saddr, const u16 sport,
-				       const u32 daddr, const u16 dport,
+				       const __be32 saddr, const __be16 sport,
+				       const __be32 daddr, const __be16 dport,
 				       const int dif)
 {
 	struct sock *sk;
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index f624271..ce6da97 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -36,7 +36,7 @@
  * @ts_needaddr - Need to record addr of outgoing dev
  */
 struct ip_options {
-	__u32		faddr;
+	__be32		faddr;
 	unsigned char	optlen;
 	unsigned char	srr;
 	unsigned char	rr;
@@ -62,9 +62,9 @@
 	u16			inet6_rsk_offset;
 	/* 2 bytes hole, try to pack */
 #endif
-	u32			loc_addr;
-	u32			rmt_addr;
-	u16			rmt_port;
+	__be32			loc_addr;
+	__be32			rmt_addr;
+	__be16			rmt_port;
 	u16			snd_wscale : 4, 
 				rcv_wscale : 4, 
 				tstamp_ok  : 1,
@@ -110,15 +110,15 @@
 	struct ipv6_pinfo	*pinet6;
 #endif
 	/* Socket demultiplex comparisons on incoming packets. */
-	__u32			daddr;
-	__u32			rcv_saddr;
-	__u16			dport;
+	__be32			daddr;
+	__be32			rcv_saddr;
+	__be16			dport;
 	__u16			num;
-	__u32			saddr;
+	__be32			saddr;
 	__s16			uc_ttl;
 	__u16			cmsg_flags;
 	struct ip_options	*opt;
-	__u16			sport;
+	__be16			sport;
 	__u16			id;
 	__u8			tos;
 	__u8			mc_ttl;
@@ -129,7 +129,7 @@
 				hdrincl:1,
 				mc_loop:1;
 	int			mc_index;
-	__u32			mc_addr;
+	__be32			mc_addr;
 	struct ip_mc_socklist	*mc_list;
 	struct {
 		unsigned int		flags;
@@ -137,7 +137,7 @@
 		struct ip_options	*opt;
 		struct rtable		*rt;
 		int			length; /* Total length of all frames */
-		u32			addr;
+		__be32			addr;
 		struct flowi		fl;
 	} cork;
 };
@@ -167,10 +167,10 @@
 
 extern int inet_sk_rebuild_header(struct sock *sk);
 
-static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
-					const __u32 faddr, const __u16 fport)
+static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport,
+					const __be32 faddr, const __be16 fport)
 {
-	unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
+	unsigned int h = ((__force __u32)laddr ^ lport) ^ ((__force __u32)faddr ^ (__force __u32)fport);
 	h ^= h >> 16;
 	h ^= h >> 8;
 	return h;
@@ -179,10 +179,10 @@
 static inline int inet_sk_ehashfn(const struct sock *sk)
 {
 	const struct inet_sock *inet = inet_sk(sk);
-	const __u32 laddr = inet->rcv_saddr;
+	const __be32 laddr = inet->rcv_saddr;
 	const __u16 lport = inet->num;
-	const __u32 faddr = inet->daddr;
-	const __u16 fport = inet->dport;
+	const __be32 faddr = inet->daddr;
+	const __be16 fport = inet->dport;
 
 	return inet_ehashfn(laddr, lport, faddr, fport);
 }
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 600cb54..6d14c22 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -120,10 +120,10 @@
 	unsigned char		tw_rcv_wscale;
 	/* Socket demultiplex comparisons on incoming packets. */
 	/* these five are in inet_sock */
-	__u16			tw_sport;
-	__u32			tw_daddr __attribute__((aligned(INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES)));
-	__u32			tw_rcv_saddr;
-	__u16			tw_dport;
+	__be16			tw_sport;
+	__be32			tw_daddr __attribute__((aligned(INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES)));
+	__be32			tw_rcv_saddr;
+	__be16			tw_dport;
 	__u16			tw_num;
 	/* And these are ours. */
 	__u8			tw_ipv6only:1;
@@ -186,7 +186,7 @@
 	return (struct inet_timewait_sock *)sk;
 }
 
-static inline u32 inet_rcv_saddr(const struct sock *sk)
+static inline __be32 inet_rcv_saddr(const struct sock *sk)
 {
 	return likely(sk->sk_state != TCP_TIME_WAIT) ?
 		inet_sk(sk)->rcv_saddr : inet_twsk(sk)->tw_rcv_saddr;
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 0965515..925573f 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -22,7 +22,7 @@
 	unsigned long		dtime;		/* the time of last use of not
 						 * referenced entries */
 	atomic_t		refcnt;
-	__u32			v4daddr;	/* peer's address */
+	__be32			v4daddr;	/* peer's address */
 	__u16			avl_height;
 	__u16			ip_id_count;	/* IP ID for the next packet */
 	atomic_t		rid;		/* Frag reception counter */
@@ -33,7 +33,7 @@
 void			inet_initpeers(void) __init;
 
 /* can be called with or without local BH being disabled */
-struct inet_peer	*inet_getpeer(__u32 daddr, int create);
+struct inet_peer	*inet_getpeer(__be32 daddr, int create);
 
 extern spinlock_t inet_peer_unused_lock;
 extern struct inet_peer **inet_peer_unused_tailp;
diff --git a/include/net/ip.h b/include/net/ip.h
index 98f9084..b6d95e5 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -45,7 +45,7 @@
 
 struct ipcm_cookie
 {
-	u32			addr;
+	__be32			addr;
 	int			oif;
 	struct ip_options	*opt;
 };
@@ -86,7 +86,7 @@
  */
 
 extern int		ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
-					      u32 saddr, u32 daddr,
+					      __be32 saddr, __be32 daddr,
 					      struct ip_options *opt);
 extern int		ip_rcv(struct sk_buff *skb, struct net_device *dev,
 			       struct packet_type *pt, struct net_device *orig_dev);
@@ -335,7 +335,7 @@
  *	Functions provided by ip_options.c
  */
  
-extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 daddr, struct rtable *rt, int is_frag);
+extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, __be32 daddr, struct rtable *rt, int is_frag);
 extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
 extern void ip_options_fragment(struct sk_buff *skb);
 extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb);
@@ -363,8 +363,8 @@
 
 extern int 	ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
 extern void	ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
-			      u16 port, u32 info, u8 *payload);
-extern void	ip_local_error(struct sock *sk, int err, u32 daddr, u16 dport,
+			      __be16 port, u32 info, u8 *payload);
+extern void	ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
 			       u32 info);
 
 /* sysctl helpers - any sysctl which holds a value that ends up being
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index fcc159a..8222914 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -30,13 +30,13 @@
 	u8			fc_type;
 	/* 1 byte unused */
 	u32			fc_table;
-	u32			fc_dst;
-	u32			fc_src;
-	u32			fc_gw;
+	__be32			fc_dst;
+	__be32			fc_src;
+	__be32			fc_gw;
 	int			fc_oif;
 	u32			fc_flags;
 	u32			fc_priority;
-	u32			fc_prefsrc;
+	__be32			fc_prefsrc;
 	struct nlattr		*fc_mx;
 	struct rtnexthop	*fc_mp;
 	int			fc_mx_len;
@@ -63,7 +63,7 @@
 	__u32			nh_tclassid;
 #endif
 	int			nh_oif;
-	u32			nh_gw;
+	__be32			nh_gw;
 };
 
 /*
@@ -78,7 +78,7 @@
 	int			fib_dead;
 	unsigned		fib_flags;
 	int			fib_protocol;
-	u32			fib_prefsrc;
+	__be32			fib_prefsrc;
 	u32			fib_priority;
 	u32			fib_metrics[RTAX_MAX];
 #define fib_mtu fib_metrics[RTAX_MTU-1]
@@ -107,8 +107,8 @@
 	unsigned char	type;
 	unsigned char	scope;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	__u32           network;
-	__u32           netmask;
+	__be32          network;
+	__be32          netmask;
 #endif
 	struct fib_info *fi;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -117,7 +117,7 @@
 };
 
 struct fib_result_nl {
-	u32		fl_addr;   /* To be looked up*/ 
+	__be32		fl_addr;   /* To be looked up*/
 	u32		fl_fwmark; 
 	unsigned char	fl_tos;
 	unsigned char   fl_scope;
@@ -222,17 +222,17 @@
 extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb);
-extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-			       struct net_device *dev, u32 *spec_dst, u32 *itag);
+extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
+			       struct net_device *dev, __be32 *spec_dst, u32 *itag);
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
 
 struct rtentry;
 
 /* Exported by fib_semantics.c */
-extern int ip_fib_check_default(u32 gw, struct net_device *dev);
-extern int fib_sync_down(u32 local, struct net_device *dev, int force);
+extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
+extern int fib_sync_down(__be32 local, struct net_device *dev, int force);
 extern int fib_sync_up(struct net_device *dev);
-extern u32  __fib_res_prefsrc(struct fib_result *res);
+extern __be32  __fib_res_prefsrc(struct fib_result *res);
 
 /* Exported by fib_hash.c */
 extern struct fib_table *fib_hash_init(u32 id);
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
index ac747b6..beffdd6 100644
--- a/include/net/ip_mp_alg.h
+++ b/include/net/ip_mp_alg.h
@@ -17,7 +17,7 @@
 	void	(*mp_alg_select_route)(const struct flowi *flp,
 				       struct rtable *rth, struct rtable **rp);
 	void	(*mp_alg_flush)(void);
-	void	(*mp_alg_set_nhinfo)(__u32 network, __u32 netmask,
+	void	(*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
 				     unsigned char prefixlen,
 				     const struct fib_nh *nh);
 	void	(*mp_alg_remove)(struct rtable *rth);
@@ -59,7 +59,7 @@
 }
 
 static inline void multipath_set_nhinfo(struct rtable *rth,
-					__u32 network, __u32 netmask,
+					__be32 network, __be32 netmask,
 					unsigned char prefixlen,
 					const struct fib_nh *nh)
 {
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 3b57b15..49c717e 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -100,22 +100,22 @@
 struct ip_vs_service_user {
 	/* virtual service addresses */
 	u_int16_t		protocol;
-	u_int32_t		addr;		/* virtual ip address */
-	u_int16_t		port;
+	__be32			addr;		/* virtual ip address */
+	__be16			port;
 	u_int32_t		fwmark;		/* firwall mark of service */
 
 	/* virtual service options */
 	char			sched_name[IP_VS_SCHEDNAME_MAXLEN];
 	unsigned		flags;		/* virtual service flags */
 	unsigned		timeout;	/* persistent timeout in sec */
-	u_int32_t		netmask;	/* persistent netmask */
+	__be32			netmask;	/* persistent netmask */
 };
 
 
 struct ip_vs_dest_user {
 	/* destination server address */
-	u_int32_t		addr;
-	u_int16_t		port;
+	__be32			addr;
+	__be16			port;
 
 	/* real server options */
 	unsigned		conn_flags;	/* connection flags */
@@ -163,15 +163,15 @@
 struct ip_vs_service_entry {
 	/* which service: user fills in these */
 	u_int16_t		protocol;
-	u_int32_t		addr;		/* virtual address */
-	u_int16_t		port;
+	__be32			addr;		/* virtual address */
+	__be16			port;
 	u_int32_t		fwmark;		/* firwall mark of service */
 
 	/* service options */
 	char			sched_name[IP_VS_SCHEDNAME_MAXLEN];
 	unsigned		flags;          /* virtual service flags */
 	unsigned		timeout;	/* persistent timeout */
-	u_int32_t		netmask;	/* persistent netmask */
+	__be32			netmask;	/* persistent netmask */
 
 	/* number of real servers */
 	unsigned int		num_dests;
@@ -182,8 +182,8 @@
 
 
 struct ip_vs_dest_entry {
-	u_int32_t		addr;		/* destination address */
-	u_int16_t		port;
+	__be32			addr;		/* destination address */
+	__be16			port;
 	unsigned		conn_flags;	/* connection flags */
 	int			weight;		/* destination weight */
 
@@ -203,8 +203,8 @@
 struct ip_vs_get_dests {
 	/* which service: user fills in these */
 	u_int16_t		protocol;
-	u_int32_t		addr;		/* virtual address */
-	u_int16_t		port;
+	__be32			addr;		/* virtual address */
+	__be16			port;
 	u_int32_t		fwmark;		/* firwall mark of service */
 
 	/* number of real servers */
@@ -502,12 +502,12 @@
 	struct list_head        c_list;         /* hashed list heads */
 
 	/* Protocol, addresses and port numbers */
-	__u32                   caddr;          /* client address */
-	__u32                   vaddr;          /* virtual address */
-	__u32                   daddr;          /* destination address */
-	__u16                   cport;
-	__u16                   vport;
-	__u16                   dport;
+	__be32                   caddr;          /* client address */
+	__be32                   vaddr;          /* virtual address */
+	__be32                   daddr;          /* destination address */
+	__be16                   cport;
+	__be16                   vport;
+	__be16                   dport;
 	__u16                   protocol;       /* Which protocol (TCP/UDP) */
 
 	/* counter and timer */
@@ -554,12 +554,12 @@
 	atomic_t		usecnt;   /* use counter */
 
 	__u16			protocol; /* which protocol (TCP/UDP) */
-	__u32			addr;	  /* IP address for virtual service */
-	__u16			port;	  /* port number for the service */
+	__be32			addr;	  /* IP address for virtual service */
+	__be16			port;	  /* port number for the service */
 	__u32                   fwmark;   /* firewall mark of the service */
 	unsigned		flags;	  /* service status flags */
 	unsigned		timeout;  /* persistent timeout in ticks */
-	__u32			netmask;  /* grouping granularity */
+	__be32			netmask;  /* grouping granularity */
 
 	struct list_head	destinations;  /* real server d-linked list */
 	__u32			num_dests;     /* number of servers */
@@ -581,8 +581,8 @@
 	struct list_head	n_list;   /* for the dests in the service */
 	struct list_head	d_list;   /* for table with all the dests */
 
-	__u32			addr;		/* IP address of the server */
-	__u16			port;		/* port number of the server */
+	__be32			addr;		/* IP address of the server */
+	__be16			port;		/* port number of the server */
 	volatile unsigned	flags;		/* dest status flags */
 	atomic_t		conn_flags;	/* flags to copy to conn */
 	atomic_t		weight;		/* server weight */
@@ -605,8 +605,8 @@
 	/* for virtual service */
 	struct ip_vs_service	*svc;		/* service it belongs to */
 	__u16			protocol;	/* which protocol (TCP/UDP) */
-	__u32			vaddr;		/* virtual IP address */
-	__u16			vport;		/* virtual port number */
+	__be32			vaddr;		/* virtual IP address */
+	__be16			vport;		/* virtual port number */
 	__u32			vfwmark;	/* firewall mark of service */
 };
 
@@ -648,7 +648,7 @@
 	/* members for application incarnations */
 	struct list_head	p_list;		/* member in proto app list */
 	struct ip_vs_app	*app;		/* its real application */
-	__u16			port;		/* port number in net order */
+	__be16			port;		/* port number in net order */
 	atomic_t		usecnt;		/* usage counter */
 
 	/* output hook: return false if can't linearize. diff set for TCP.  */
@@ -740,11 +740,11 @@
 };
 
 extern struct ip_vs_conn *ip_vs_conn_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
 extern struct ip_vs_conn *ip_vs_ct_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
 extern struct ip_vs_conn *ip_vs_conn_out_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
 
 /* put back the conn without restarting its timer */
 static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
@@ -752,11 +752,11 @@
 	atomic_dec(&cp->refcnt);
 }
 extern void ip_vs_conn_put(struct ip_vs_conn *cp);
-extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __u16 cport);
+extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
 
 extern struct ip_vs_conn *
-ip_vs_conn_new(int proto, __u32 caddr, __u16 cport, __u32 vaddr, __u16 vport,
-	       __u32 daddr, __u16 dport, unsigned flags,
+ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport,
+	       __be32 daddr, __be16 dport, unsigned flags,
 	       struct ip_vs_dest *dest);
 extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
 
@@ -887,7 +887,7 @@
 extern struct ip_vs_stats ip_vs_stats;
 
 extern struct ip_vs_service *
-ip_vs_service_get(__u32 fwmark, __u16 protocol, __u32 vaddr, __u16 vport);
+ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport);
 
 static inline void ip_vs_service_put(struct ip_vs_service *svc)
 {
@@ -895,7 +895,7 @@
 }
 
 extern struct ip_vs_dest *
-ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport);
+ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport);
 extern int ip_vs_use_count_inc(void);
 extern void ip_vs_use_count_dec(void);
 extern int ip_vs_control_init(void);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 72bf47b..8223c44 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -318,8 +318,8 @@
 
 #ifndef __HAVE_ARCH_ADDR_SET
 static inline void ipv6_addr_set(struct in6_addr *addr, 
-				     __u32 w1, __u32 w2,
-				     __u32 w3, __u32 w4)
+				     __be32 w1, __be32 w2,
+				     __be32 w3, __be32 w4)
 {
 	addr->s6_addr32[0] = w1;
 	addr->s6_addr32[1] = w2;
@@ -337,7 +337,7 @@
 		a1->s6_addr32[3] == a2->s6_addr32[3]);
 }
 
-static inline int __ipv6_prefix_equal(const u32 *a1, const u32 *a2,
+static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
 				      unsigned int prefixlen)
 {
 	unsigned pdw, pbi;
diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h
index 1c73bdb..9592c37 100644
--- a/include/net/irda/irlan_common.h
+++ b/include/net/irda/irlan_common.h
@@ -98,7 +98,15 @@
 #define IRLAN_SHORT  1
 #define IRLAN_ARRAY  2
 
-#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_MAX_HEADER)
+/* IrLAN sits on top if IrTTP */
+#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER)
+/* 1 byte for the command code and 1 byte for the parameter count */
+#define IRLAN_CMD_HEADER 2
+
+#define IRLAN_STRING_PARAMETER_LEN(name, value) (1 + strlen((name)) + 2 \
+						+ strlen ((value)))
+#define IRLAN_BYTE_PARAMETER_LEN(name)          (1 + strlen((name)) + 2 + 1)
+#define IRLAN_SHORT_PARAMETER_LEN(name)         (1 + strlen((name)) + 2 + 2)
 
 /*
  *  IrLAN client
diff --git a/include/net/irda/irlap_frame.h b/include/net/irda/irlap_frame.h
index 3452ae2..9dd54a5 100644
--- a/include/net/irda/irlap_frame.h
+++ b/include/net/irda/irlap_frame.h
@@ -74,6 +74,19 @@
 
 #define PF_BIT    0x10 /* Poll/final bit */
 
+/* Some IrLAP field lengths */
+/*
+ * Only baud rate triplet is 4 bytes (PV can be 2 bytes).
+ * All others params (7) are 3 bytes, so that's 7*3 + 1*4 bytes.
+ */
+#define IRLAP_NEGOCIATION_PARAMS_LEN 25
+#define IRLAP_DISCOVERY_INFO_LEN     32
+
+struct disc_frame {
+	__u8 caddr;          /* Connection address */
+	__u8 control;
+} IRDA_PACK;
+
 struct xid_frame {
 	__u8  caddr; /* Connection address */
 	__u8  control;
@@ -95,11 +108,25 @@
 struct ua_frame {
 	__u8 caddr;
 	__u8 control;
-
 	__u32 saddr; /* Source device address */
 	__u32 daddr; /* Dest device address */
 } IRDA_PACK;
-	
+
+struct dm_frame {
+	__u8 caddr;          /* Connection address */
+	__u8 control;
+} IRDA_PACK;
+
+struct rd_frame {
+	__u8 caddr;          /* Connection address */
+	__u8 control;
+} IRDA_PACK;
+
+struct rr_frame {
+	__u8 caddr;          /* Connection address */
+	__u8 control;
+} IRDA_PACK;
+
 struct i_frame {
 	__u8 caddr;
 	__u8 control;
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index 11ecfa5..e212b9b 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -48,7 +48,7 @@
 #define DEV_ADDR_ANY  0xffffffff
 
 #define LMP_HEADER          2    /* Dest LSAP + Source LSAP */
-#define LMP_CONTROL_HEADER  4
+#define LMP_CONTROL_HEADER  4    /* LMP_HEADER + opcode + parameter */
 #define LMP_PID_HEADER      1    /* Used by Ultra */
 #define LMP_MAX_HEADER      (LMP_CONTROL_HEADER+LAP_MAX_HEADER)
 
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 6692430..190bfdb 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -96,7 +96,7 @@
 struct netlbl_dom_map;
 
 /* Domain mapping operations */
-int netlbl_domhsh_remove(const char *domain);
+int netlbl_domhsh_remove(const char *domain, u32 audit_secid);
 
 /* LSM security attributes */
 struct netlbl_lsm_cache {
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 4ab68a7..ce5cba1 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -831,6 +831,9 @@
 #define NLA_PUT_U32(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, u32, attrtype, value)
 
+#define NLA_PUT_BE32(skb, attrtype, value) \
+	NLA_PUT_TYPE(skb, __be32, attrtype, value)
+
 #define NLA_PUT_U64(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, u64, attrtype, value)
 
@@ -853,6 +856,15 @@
 }
 
 /**
+ * nla_get_be32 - return payload of __be32 attribute
+ * @nla: __be32 netlink attribute
+ */
+static inline __be32 nla_get_be32(struct nlattr *nla)
+{
+	return *(__be32 *) nla_data(nla);
+}
+
+/**
  * nla_get_u16 - return payload of u16 attribute
  * @nla: u16 netlink attribute
  */
diff --git a/include/net/route.h b/include/net/route.h
index 7f93ac0..486e37a 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -62,18 +62,18 @@
 	__u16			rt_type;
 	__u16			rt_multipath_alg;
 
-	__u32			rt_dst;	/* Path destination	*/
-	__u32			rt_src;	/* Path source		*/
+	__be32			rt_dst;	/* Path destination	*/
+	__be32			rt_src;	/* Path source		*/
 	int			rt_iif;
 
 	/* Info on neighbour */
-	__u32			rt_gateway;
+	__be32			rt_gateway;
 
 	/* Cache lookup keys */
 	struct flowi		fl;
 
 	/* Miscellaneous cached information */
-	__u32			rt_spec_dst; /* RFC1122 specific destination */
+	__be32			rt_spec_dst; /* RFC1122 specific destination */
 	struct inet_peer	*peer; /* long-living peer info */
 };
 
@@ -109,18 +109,18 @@
 
 struct in_device;
 extern int		ip_rt_init(void);
-extern void		ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
-				       u32 src, struct net_device *dev);
+extern void		ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
+				       __be32 src, struct net_device *dev);
 extern void		ip_rt_advice(struct rtable **rp, int advice);
 extern void		rt_cache_flush(int how);
 extern int		__ip_route_output_key(struct rtable **, const struct flowi *flp);
 extern int		ip_route_output_key(struct rtable **, struct flowi *flp);
 extern int		ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags);
-extern int		ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
+extern int		ip_route_input(struct sk_buff*, __be32 dst, __be32 src, u8 tos, struct net_device *devin);
 extern unsigned short	ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
 extern void		ip_rt_send_redirect(struct sk_buff *skb);
 
-extern unsigned		inet_addr_type(u32 addr);
+extern unsigned		inet_addr_type(__be32 addr);
 extern void		ip_rt_multicast_event(struct in_device *);
 extern int		ip_rt_ioctl(unsigned int cmd, void __user *arg);
 extern void		ip_rt_get_source(u8 *src, struct rtable *rt);
@@ -144,9 +144,9 @@
 	return ip_tos2prio[IPTOS_TOS(tos)>>1];
 }
 
-static inline int ip_route_connect(struct rtable **rp, u32 dst,
-				   u32 src, u32 tos, int oif, u8 protocol,
-				   u16 sport, u16 dport, struct sock *sk)
+static inline int ip_route_connect(struct rtable **rp, __be32 dst,
+				   __be32 src, u32 tos, int oif, u8 protocol,
+				   __be16 sport, __be16 dport, struct sock *sk)
 {
 	struct flowi fl = { .oif = oif,
 			    .nl_u = { .ip4_u = { .daddr = dst,
@@ -172,7 +172,7 @@
 }
 
 static inline int ip_route_newports(struct rtable **rp, u8 protocol,
-				    u16 sport, u16 dport, struct sock *sk)
+				    __be16 sport, __be16 dport, struct sock *sk)
 {
 	if (sport != (*rp)->fl.fl_ip_sport ||
 	    dport != (*rp)->fl.fl_ip_dport) {
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 11e0b1d..1e2a4dd 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -437,8 +437,8 @@
 
 static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
 {
-	__u32 *a1 = token1;
-	__u32 *a2 = token2;
+	__be32 *a1 = token1;
+	__be32 *a2 = token2;
 	int pdw;
 	int pbi;
 
@@ -450,7 +450,7 @@
 			return 0;
 
 	if (pbi) {
-		__u32 mask;
+		__be32 mask;
 
 		mask = htonl((0xffffffff) << (32 - pbi));
 
@@ -462,9 +462,9 @@
 }
 
 static __inline__
-u16 xfrm_flowi_sport(struct flowi *fl)
+__be16 xfrm_flowi_sport(struct flowi *fl)
 {
-	u16 port;
+	__be16 port;
 	switch(fl->proto) {
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
@@ -487,9 +487,9 @@
 }
 
 static __inline__
-u16 xfrm_flowi_dport(struct flowi *fl)
+__be16 xfrm_flowi_dport(struct flowi *fl)
 {
-	u16 port;
+	__be16 port;
 	switch(fl->proto) {
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
@@ -912,7 +912,7 @@
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
 extern int xfrm_state_update(struct xfrm_state *x);
-extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
 #ifdef CONFIG_XFRM_SUB_POLICY
 extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
@@ -935,8 +935,8 @@
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
-extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
-extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
+extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
+extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_notify(struct xfrm_state *x, int event);
 extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
@@ -945,7 +945,7 @@
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
+extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
 extern int xfrm6_rcv(struct sk_buff **pskb);
 extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
 			    xfrm_address_t *saddr, u8 proto);
@@ -989,7 +989,7 @@
 struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
 void xfrm_policy_flush(u8 type);
 u32 xfrm_get_acqseq(void);
-void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
+void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
 struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
 				  xfrm_address_t *daddr, xfrm_address_t *saddr, 
 				  int create, unsigned short family);
@@ -1004,7 +1004,7 @@
 extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
 
 extern void xfrm_input_init(void);
-extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq);
+extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
 
 extern void xfrm_probe_algs(void);
 extern int xfrm_count_auth_supported(void);
diff --git a/kernel/acct.c b/kernel/acct.c
index 2a7c933..f4330ac 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -483,10 +483,14 @@
 	ac.ac_ppid = current->parent->tgid;
 #endif
 
-	read_lock(&tasklist_lock);	/* pin current->signal */
+	mutex_lock(&tty_mutex);
+	/* FIXME: Whoever is responsible for current->signal locking needs
+	   to use the same locking all over the kernel and document it */
+	read_lock(&tasklist_lock);
 	ac.ac_tty = current->signal->tty ?
 		old_encode_dev(tty_devnum(current->signal->tty)) : 0;
 	read_unlock(&tasklist_lock);
+	mutex_unlock(&tty_mutex);
 
 	spin_lock_irq(&current->sighand->siglock);
 	ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index fb83c5c..1051476 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -817,6 +817,8 @@
 		audit_log_format(ab, " success=%s exit=%ld", 
 				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
 				 context->return_code);
+
+	mutex_lock(&tty_mutex);
 	if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
 		tty = tsk->signal->tty->name;
 	else
@@ -838,6 +840,9 @@
 		  context->gid,
 		  context->euid, context->suid, context->fsuid,
 		  context->egid, context->sgid, context->fsgid, tty);
+
+	mutex_unlock(&tty_mutex);
+
 	audit_log_task_info(ab, tsk);
 	if (context->filterkey) {
 		audit_log_format(ab, " key=");
diff --git a/kernel/capability.c b/kernel/capability.c
index c7685ad..edb845a 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -133,7 +133,7 @@
      int found = 0;
 
      do_each_thread(g, target) {
-             if (target == current || target->pid == 1)
+             if (target == current || is_init(target))
                      continue;
              found = 1;
 	     if (security_capset_check(target, effective, inheritable,
diff --git a/kernel/compat.c b/kernel/compat.c
index 126dee9..75573e5 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -22,6 +22,7 @@
 #include <linux/security.h>
 #include <linux/timex.h>
 #include <linux/migrate.h>
+#include <linux/posix-timers.h>
 
 #include <asm/uaccess.h>
 
@@ -601,6 +602,30 @@
 	return err;
 } 
 
+static long compat_clock_nanosleep_restart(struct restart_block *restart)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec tu;
+	struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1);
+
+	restart->arg1 = (unsigned long) &tu;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = clock_nanosleep_restart(restart);
+	set_fs(oldfs);
+
+	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+	    put_compat_timespec(&tu, rmtp))
+		return -EFAULT;
+
+	if (err == -ERESTART_RESTARTBLOCK) {
+		restart->fn = compat_clock_nanosleep_restart;
+		restart->arg1 = (unsigned long) rmtp;
+	}
+	return err;
+}
+
 long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
 			    struct compat_timespec __user *rqtp,
 			    struct compat_timespec __user *rmtp)
@@ -608,6 +633,7 @@
 	long err;
 	mm_segment_t oldfs;
 	struct timespec in, out; 
+	struct restart_block *restart;
 
 	if (get_compat_timespec(&in, rqtp)) 
 		return -EFAULT;
@@ -618,9 +644,16 @@
 				  (struct timespec __user *) &in,
 				  (struct timespec __user *) &out);
 	set_fs(oldfs);
+
 	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
 	    put_compat_timespec(&out, rmtp))
 		return -EFAULT;
+
+	if (err == -ERESTART_RESTARTBLOCK) {
+		restart = &current_thread_info()->restart_block;
+		restart->fn = compat_clock_nanosleep_restart;
+		restart->arg1 = (unsigned long) rmtp;
+	}
 	return err;	
 } 
 
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 1b32c2c..8c3c400 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -240,7 +240,7 @@
  * A cpuset can only be deleted if both its 'count' of using tasks
  * is zero, and its list of 'children' cpusets is empty.  Since all
  * tasks in the system use _some_ cpuset, and since there is always at
- * least one task in the system (init, pid == 1), therefore, top_cpuset
+ * least one task in the system (init), therefore, top_cpuset
  * always has either children cpusets and/or using tasks.  So we don't
  * need a special hack to ensure that top_cpuset cannot be deleted.
  *
@@ -912,6 +912,10 @@
 	int fudge;
 	int retval;
 
+	/* top_cpuset.mems_allowed tracks node_online_map; it's read-only */
+	if (cs == &top_cpuset)
+		return -EACCES;
+
 	trialcs = *cs;
 	retval = nodelist_parse(buf, trialcs.mems_allowed);
 	if (retval < 0)
@@ -1221,7 +1225,12 @@
 
 	task_lock(tsk);
 	oldcs = tsk->cpuset;
-	if (!oldcs) {
+	/*
+	 * After getting 'oldcs' cpuset ptr, be sure still not exiting.
+	 * If 'oldcs' might be the top_cpuset due to the_top_cpuset_hack
+	 * then fail this attach_task(), to avoid breaking top_cpuset.count.
+	 */
+	if (tsk->flags & PF_EXITING) {
 		task_unlock(tsk);
 		mutex_unlock(&callback_mutex);
 		put_task_struct(tsk);
@@ -2036,33 +2045,104 @@
 	return err;
 }
 
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_MEMORY_HOTPLUG)
+/*
+ * If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs
+ * or memory nodes, we need to walk over the cpuset hierarchy,
+ * removing that CPU or node from all cpusets.  If this removes the
+ * last CPU or node from a cpuset, then the guarantee_online_cpus()
+ * or guarantee_online_mems() code will use that emptied cpusets
+ * parent online CPUs or nodes.  Cpusets that were already empty of
+ * CPUs or nodes are left empty.
+ *
+ * This routine is intentionally inefficient in a couple of regards.
+ * It will check all cpusets in a subtree even if the top cpuset of
+ * the subtree has no offline CPUs or nodes.  It checks both CPUs and
+ * nodes, even though the caller could have been coded to know that
+ * only one of CPUs or nodes needed to be checked on a given call.
+ * This was done to minimize text size rather than cpu cycles.
+ *
+ * Call with both manage_mutex and callback_mutex held.
+ *
+ * Recursive, on depth of cpuset subtree.
+ */
+
+static void guarantee_online_cpus_mems_in_subtree(const struct cpuset *cur)
+{
+	struct cpuset *c;
+
+	/* Each of our child cpusets mems must be online */
+	list_for_each_entry(c, &cur->children, sibling) {
+		guarantee_online_cpus_mems_in_subtree(c);
+		if (!cpus_empty(c->cpus_allowed))
+			guarantee_online_cpus(c, &c->cpus_allowed);
+		if (!nodes_empty(c->mems_allowed))
+			guarantee_online_mems(c, &c->mems_allowed);
+	}
+}
+
+/*
+ * The cpus_allowed and mems_allowed nodemasks in the top_cpuset track
+ * cpu_online_map and node_online_map.  Force the top cpuset to track
+ * whats online after any CPU or memory node hotplug or unplug event.
+ *
+ * To ensure that we don't remove a CPU or node from the top cpuset
+ * that is currently in use by a child cpuset (which would violate
+ * the rule that cpusets must be subsets of their parent), we first
+ * call the recursive routine guarantee_online_cpus_mems_in_subtree().
+ *
+ * Since there are two callers of this routine, one for CPU hotplug
+ * events and one for memory node hotplug events, we could have coded
+ * two separate routines here.  We code it as a single common routine
+ * in order to minimize text size.
+ */
+
+static void common_cpu_mem_hotplug_unplug(void)
+{
+	mutex_lock(&manage_mutex);
+	mutex_lock(&callback_mutex);
+
+	guarantee_online_cpus_mems_in_subtree(&top_cpuset);
+	top_cpuset.cpus_allowed = cpu_online_map;
+	top_cpuset.mems_allowed = node_online_map;
+
+	mutex_unlock(&callback_mutex);
+	mutex_unlock(&manage_mutex);
+}
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
 /*
  * The top_cpuset tracks what CPUs and Memory Nodes are online,
  * period.  This is necessary in order to make cpusets transparent
  * (of no affect) on systems that are actively using CPU hotplug
  * but making no active use of cpusets.
  *
- * This handles CPU hotplug (cpuhp) events.  If someday Memory
- * Nodes can be hotplugged (dynamically changing node_online_map)
- * then we should handle that too, perhaps in a similar way.
+ * This routine ensures that top_cpuset.cpus_allowed tracks
+ * cpu_online_map on each CPU hotplug (cpuhp) event.
  */
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int cpuset_handle_cpuhp(struct notifier_block *nb,
 				unsigned long phase, void *cpu)
 {
-	mutex_lock(&manage_mutex);
-	mutex_lock(&callback_mutex);
-
-	top_cpuset.cpus_allowed = cpu_online_map;
-
-	mutex_unlock(&callback_mutex);
-	mutex_unlock(&manage_mutex);
-
+	common_cpu_mem_hotplug_unplug();
 	return 0;
 }
 #endif
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ * Keep top_cpuset.mems_allowed tracking node_online_map.
+ * Call this routine anytime after you change node_online_map.
+ * See also the previous routine cpuset_handle_cpuhp().
+ */
+
+void cpuset_track_online_nodes()
+{
+	common_cpu_mem_hotplug_unplug();
+}
+#endif
+
 /**
  * cpuset_init_smp - initialize cpus_allowed
  *
diff --git a/kernel/exit.c b/kernel/exit.c
index d891883..2e4c13c 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -219,7 +219,7 @@
 	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p == ignored_task
 				|| p->exit_state
-				|| p->real_parent->pid == 1)
+				|| is_init(p->real_parent))
 			continue;
 		if (process_group(p->real_parent) != pgrp
 			    && p->real_parent->signal->session == p->signal->session) {
@@ -249,17 +249,6 @@
 	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p->state != TASK_STOPPED)
 			continue;
-
-		/* If p is stopped by a debugger on a signal that won't
-		   stop it, then don't count p as stopped.  This isn't
-		   perfect but it's a good approximation.  */
-		if (unlikely (p->ptrace)
-		    && p->exit_code != SIGSTOP
-		    && p->exit_code != SIGTSTP
-		    && p->exit_code != SIGTTOU
-		    && p->exit_code != SIGTTIN)
-			continue;
-
 		retval = 1;
 		break;
 	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
@@ -292,9 +281,7 @@
 	/* Set the exit signal to SIGCHLD so we signal init on exit */
 	current->exit_signal = SIGCHLD;
 
-	if ((current->policy == SCHED_NORMAL ||
-			current->policy == SCHED_BATCH)
-				&& (task_nice(current) < 0))
+	if (!has_rt_policy(current) && (task_nice(current) < 0))
 		set_user_nice(current, 0);
 	/* cpus_allowed? */
 	/* rt_priority? */
@@ -487,6 +474,18 @@
 
 EXPORT_SYMBOL(put_files_struct);
 
+void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
+{
+	struct files_struct *old;
+
+	old = tsk->files;
+	task_lock(tsk);
+	tsk->files = files;
+	task_unlock(tsk);
+	put_files_struct(old);
+}
+EXPORT_SYMBOL(reset_files_struct);
+
 static inline void __exit_files(struct task_struct *tsk)
 {
 	struct files_struct * files = tsk->files;
@@ -954,15 +953,15 @@
 	if (tsk->splice_pipe)
 		__free_pipe_info(tsk->splice_pipe);
 
-	/* PF_DEAD causes final put_task_struct after we schedule. */
 	preempt_disable();
-	BUG_ON(tsk->flags & PF_DEAD);
-	tsk->flags |= PF_DEAD;
+	/* causes final put_task_struct in finish_task_switch(). */
+	tsk->state = TASK_DEAD;
 
 	schedule();
 	BUG();
 	/* Avoid "noreturn function does return".  */
-	for (;;) ;
+	for (;;)
+		cpu_relax();	/* For when BUG is null */
 }
 
 EXPORT_SYMBOL_GPL(do_exit);
@@ -971,7 +970,7 @@
 {
 	if (comp)
 		complete(comp);
-	
+
 	do_exit(code);
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index a0dad84..1c999f3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -183,7 +183,9 @@
 	/* One for us, one for whoever does the "release_task()" (usually parent) */
 	atomic_set(&tsk->usage,2);
 	atomic_set(&tsk->fs_excl, 0);
+#ifdef CONFIG_BLK_DEV_IO_TRACE
 	tsk->btrace_seq = 0;
+#endif
 	tsk->splice_pipe = NULL;
 	return tsk;
 }
@@ -1061,7 +1063,11 @@
 #endif
 #ifdef CONFIG_TRACE_IRQFLAGS
 	p->irq_events = 0;
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+	p->hardirqs_enabled = 1;
+#else
 	p->hardirqs_enabled = 0;
+#endif
 	p->hardirq_enable_ip = 0;
 	p->hardirq_enable_event = 0;
 	p->hardirq_disable_ip = _THIS_IP_;
@@ -1144,7 +1150,6 @@
 
 	/* Our parent execution domain becomes current domain
 	   These must match for thread signalling to apply */
-	   
 	p->parent_exec_id = p->self_exec_id;
 
 	/* ok, now we should be set up.. */
@@ -1167,6 +1172,9 @@
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
 
+	/* for sys_ioprio_set(IOPRIO_WHO_PGRP) */
+	p->ioprio = current->ioprio;
+
 	/*
 	 * The task hasn't been attached yet, so its cpus_allowed mask will
 	 * not be changed, nor will its assigned CPU.
@@ -1226,11 +1234,6 @@
 		}
 	}
 
-	/*
-	 * inherit ioprio
-	 */
-	p->ioprio = current->ioprio;
-
 	if (likely(p->pid)) {
 		add_parent(p);
 		if (unlikely(p->ptrace & PT_PTRACED))
diff --git a/kernel/futex.c b/kernel/futex.c
index 9d260e8..4b6770e 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -389,7 +389,7 @@
 {
 	struct task_struct *p;
 
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	p = find_task_by_pid(pid);
 	if (!p)
 		goto out_unlock;
@@ -403,7 +403,7 @@
 	}
 	get_task_struct(p);
 out_unlock:
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 
 	return p;
 }
@@ -1624,7 +1624,7 @@
 		struct task_struct *p;
 
 		ret = -ESRCH;
-		read_lock(&tasklist_lock);
+		rcu_read_lock();
 		p = find_task_by_pid(pid);
 		if (!p)
 			goto err_unlock;
@@ -1633,7 +1633,7 @@
 				!capable(CAP_SYS_PTRACE))
 			goto err_unlock;
 		head = p->robust_list;
-		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 	}
 
 	if (put_user(sizeof(*head), len_ptr))
@@ -1641,7 +1641,7 @@
 	return put_user(head, head_ptr);
 
 err_unlock:
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 
 	return ret;
 }
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 21c38a7..d0ba190 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -693,7 +693,7 @@
 	return t->task == NULL;
 }
 
-static long __sched nanosleep_restart(struct restart_block *restart)
+long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
 	struct hrtimer_sleeper t;
 	struct timespec __user *rmtp;
@@ -702,13 +702,13 @@
 
 	restart->fn = do_no_restart_syscall;
 
-	hrtimer_init(&t.timer, restart->arg3, HRTIMER_ABS);
-	t.timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
+	hrtimer_init(&t.timer, restart->arg0, HRTIMER_ABS);
+	t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
 
 	if (do_nanosleep(&t, HRTIMER_ABS))
 		return 0;
 
-	rmtp = (struct timespec __user *) restart->arg2;
+	rmtp = (struct timespec __user *) restart->arg1;
 	if (rmtp) {
 		time = ktime_sub(t.timer.expires, t.timer.base->get_time());
 		if (time.tv64 <= 0)
@@ -718,7 +718,7 @@
 			return -EFAULT;
 	}
 
-	restart->fn = nanosleep_restart;
+	restart->fn = hrtimer_nanosleep_restart;
 
 	/* The other values in restart are already filled in */
 	return -ERESTART_RESTARTBLOCK;
@@ -751,11 +751,11 @@
 	}
 
 	restart = &current_thread_info()->restart_block;
-	restart->fn = nanosleep_restart;
-	restart->arg0 = t.timer.expires.tv64 & 0xFFFFFFFF;
-	restart->arg1 = t.timer.expires.tv64 >> 32;
-	restart->arg2 = (unsigned long) rmtp;
-	restart->arg3 = (unsigned long) t.timer.base->index;
+	restart->fn = hrtimer_nanosleep_restart;
+	restart->arg0 = (unsigned long) t.timer.base->index;
+	restart->arg1 = (unsigned long) rmtp;
+	restart->arg2 = t.timer.expires.tv64 & 0xFFFFFFFF;
+	restart->arg3 = t.timer.expires.tv64 >> 32;
 
 	return -ERESTART_RESTARTBLOCK;
 }
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index ac1f850..736cb0b 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -40,10 +40,6 @@
 	spin_lock_irqsave(&desc->lock, flags);
 	irq_chip_set_defaults(chip);
 	desc->chip = chip;
-	/*
-	 * For compatibility only:
-	 */
-	desc->chip = chip;
 	spin_unlock_irqrestore(&desc->lock, flags);
 
 	return 0;
@@ -146,7 +142,7 @@
 	struct irq_desc *desc = irq_desc + irq;
 
 	if (!(desc->status & IRQ_DELAYED_DISABLE))
-		irq_desc[irq].chip->mask(irq);
+		desc->chip->mask(irq);
 }
 
 /*
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 50087ec..fcdd5d2 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -40,7 +40,7 @@
 
 int kexec_should_crash(struct task_struct *p)
 {
-	if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
+	if (in_interrupt() || !p->pid || is_init(p) || panic_on_oops)
 		return 1;
 	return 0;
 }
@@ -995,7 +995,8 @@
 	image = xchg(dest_image, image);
 
 out:
-	xchg(&kexec_lock, 0); /* Release the mutex */
+	locked = xchg(&kexec_lock, 0); /* Release the mutex */
+	BUG_ON(!locked);
 	kimage_free(image);
 
 	return result;
@@ -1061,7 +1062,8 @@
 			machine_crash_shutdown(&fixed_regs);
 			machine_kexec(kexec_crash_image);
 		}
-		xchg(&kexec_lock, 0);
+		locked = xchg(&kexec_lock, 0);
+		BUG_ON(!locked);
 	}
 }
 
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index 64ab045..5d1d9073 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -122,6 +122,13 @@
 
 	len = min(len, fifo->size - fifo->in + fifo->out);
 
+	/*
+	 * Ensure that we sample the fifo->out index -before- we
+	 * start putting bytes into the kfifo.
+	 */
+
+	smp_mb();
+
 	/* first put the data starting from fifo->in to buffer end */
 	l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
 	memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
@@ -129,6 +136,13 @@
 	/* then put the rest (if any) at the beginning of the buffer */
 	memcpy(fifo->buffer, buffer + l, len - l);
 
+	/*
+	 * Ensure that we add the bytes to the kfifo -before-
+	 * we update the fifo->in index.
+	 */
+
+	smp_wmb();
+
 	fifo->in += len;
 
 	return len;
@@ -154,6 +168,13 @@
 
 	len = min(len, fifo->in - fifo->out);
 
+	/*
+	 * Ensure that we sample the fifo->in index -before- we
+	 * start removing bytes from the kfifo.
+	 */
+
+	smp_rmb();
+
 	/* first get the data from fifo->out until the end of the buffer */
 	l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
 	memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
@@ -161,6 +182,13 @@
 	/* then get the rest (if any) from the beginning of the buffer */
 	memcpy(buffer + l, fifo->buffer, len - l);
 
+	/*
+	 * Ensure that we remove the bytes from the kfifo -before-
+	 * we update the fifo->out index.
+	 */
+
+	smp_mb();
+
 	fifo->out += len;
 
 	return len;
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 5c470c5..842f801 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -176,6 +176,8 @@
 	if (pid < 0) {
 		sub_info->retval = pid;
 	} else {
+		int ret;
+
 		/*
 		 * Normally it is bogus to call wait4() from in-kernel because
 		 * wait4() wants to write the exit code to a userspace address.
@@ -185,7 +187,15 @@
 		 *
 		 * Thus the __user pointer cast is valid here.
 		 */
-		sys_wait4(pid, (int __user *) &sub_info->retval, 0, NULL);
+		sys_wait4(pid, (int __user *)&ret, 0, NULL);
+
+		/*
+		 * If ret is 0, either ____call_usermodehelper failed and the
+		 * real error code is already in sub_info->retval or
+		 * sub_info->retval is 0 anyway, so don't mess with it then.
+		 */
+		if (ret)
+			sub_info->retval = ret;
 	}
 
 	complete(sub_info->complete);
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index c088e55..e596525 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -36,6 +36,7 @@
 #include <linux/stacktrace.h>
 #include <linux/debug_locks.h>
 #include <linux/irqflags.h>
+#include <linux/utsname.h>
 
 #include <asm/sections.h>
 
@@ -121,8 +122,8 @@
  * unique.
  */
 #define iterate_chain_key(key1, key2) \
-	(((key1) << MAX_LOCKDEP_KEYS_BITS/2) ^ \
-	((key1) >> (64-MAX_LOCKDEP_KEYS_BITS/2)) ^ \
+	(((key1) << MAX_LOCKDEP_KEYS_BITS) ^ \
+	((key1) >> (64-MAX_LOCKDEP_KEYS_BITS)) ^ \
 	(key2))
 
 void lockdep_off(void)
@@ -515,6 +516,13 @@
 	return 0;
 }
 
+static void print_kernel_version(void)
+{
+	printk("%s %.*s\n", system_utsname.release,
+		(int)strcspn(system_utsname.version, " "),
+		system_utsname.version);
+}
+
 /*
  * When a circular dependency is detected, print the
  * header first:
@@ -531,6 +539,7 @@
 
 	printk("\n=======================================================\n");
 	printk(  "[ INFO: possible circular locking dependency detected ]\n");
+	print_kernel_version();
 	printk(  "-------------------------------------------------------\n");
 	printk("%s/%d is trying to acquire lock:\n",
 		curr->comm, curr->pid);
@@ -712,6 +721,7 @@
 	printk("\n======================================================\n");
 	printk(  "[ INFO: %s-safe -> %s-unsafe lock order detected ]\n",
 		irqclass, irqclass);
+	print_kernel_version();
 	printk(  "------------------------------------------------------\n");
 	printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] is trying to acquire:\n",
 		curr->comm, curr->pid,
@@ -793,6 +803,7 @@
 
 	printk("\n=============================================\n");
 	printk(  "[ INFO: possible recursive locking detected ]\n");
+	print_kernel_version();
 	printk(  "---------------------------------------------\n");
 	printk("%s/%d is trying to acquire lock:\n",
 		curr->comm, curr->pid);
@@ -1375,6 +1386,7 @@
 
 	printk("\n=========================================================\n");
 	printk(  "[ INFO: possible irq lock inversion dependency detected ]\n");
+	print_kernel_version();
 	printk(  "---------------------------------------------------------\n");
 	printk("%s/%d just changed the state of lock:\n",
 		curr->comm, curr->pid);
@@ -1469,6 +1481,7 @@
 
 	printk("\n=================================\n");
 	printk(  "[ INFO: inconsistent lock state ]\n");
+	print_kernel_version();
 	printk(  "---------------------------------\n");
 
 	printk("inconsistent {%s} -> {%s} usage.\n",
diff --git a/kernel/module.c b/kernel/module.c
index b7fe6e8..05625d5 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -933,6 +933,15 @@
 	return sprintf(buf, "0x%lx\n", sattr->address);
 }
 
+static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
+{
+	int section;
+
+	for (section = 0; section < sect_attrs->nsections; section++)
+		kfree(sect_attrs->attrs[section].name);
+	kfree(sect_attrs);
+}
+
 static void add_sect_attrs(struct module *mod, unsigned int nsect,
 		char *secstrings, Elf_Shdr *sechdrs)
 {
@@ -949,21 +958,26 @@
 			+ nloaded * sizeof(sect_attrs->attrs[0]),
 			sizeof(sect_attrs->grp.attrs[0]));
 	size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]);
-	if (! (sect_attrs = kmalloc(size[0] + size[1], GFP_KERNEL)))
+	sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
+	if (sect_attrs == NULL)
 		return;
 
 	/* Setup section attributes. */
 	sect_attrs->grp.name = "sections";
 	sect_attrs->grp.attrs = (void *)sect_attrs + size[0];
 
+	sect_attrs->nsections = 0;
 	sattr = &sect_attrs->attrs[0];
 	gattr = &sect_attrs->grp.attrs[0];
 	for (i = 0; i < nsect; i++) {
 		if (! (sechdrs[i].sh_flags & SHF_ALLOC))
 			continue;
 		sattr->address = sechdrs[i].sh_addr;
-		strlcpy(sattr->name, secstrings + sechdrs[i].sh_name,
-			MODULE_SECT_NAME_LEN);
+		sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,
+					GFP_KERNEL);
+		if (sattr->name == NULL)
+			goto out;
+		sect_attrs->nsections++;
 		sattr->mattr.show = module_sect_show;
 		sattr->mattr.store = NULL;
 		sattr->mattr.attr.name = sattr->name;
@@ -979,7 +993,7 @@
 	mod->sect_attrs = sect_attrs;
 	return;
   out:
-	kfree(sect_attrs);
+	free_sect_attrs(sect_attrs);
 }
 
 static void remove_sect_attrs(struct module *mod)
@@ -989,13 +1003,13 @@
 				   &mod->sect_attrs->grp);
 		/* We are positive that no one is using any sect attrs
 		 * at this point.  Deallocate immediately. */
-		kfree(mod->sect_attrs);
+		free_sect_attrs(mod->sect_attrs);
 		mod->sect_attrs = NULL;
 	}
 }
 
-
 #else
+
 static inline void add_sect_attrs(struct module *mod, unsigned int nsect,
 		char *sectstrings, Elf_Shdr *sechdrs)
 {
diff --git a/kernel/params.c b/kernel/params.c
index 91aea7aa..f406655 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -547,6 +547,7 @@
 					    unsigned int name_skip)
 {
 	struct module_kobject *mk;
+	int ret;
 
 	mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
 	BUG_ON(!mk);
@@ -554,7 +555,8 @@
 	mk->mod = THIS_MODULE;
 	kobj_set_kset_s(mk, module_subsys);
 	kobject_set_name(&mk->kobj, name);
-	kobject_register(&mk->kobj);
+	ret = kobject_register(&mk->kobj);
+	BUG_ON(ret < 0);
 
 	/* no need to keep the kobject if no parameter is exported */
 	if (!param_sysfs_setup(mk, kparam, num_params, name_skip)) {
@@ -684,13 +686,20 @@
  */
 static int __init param_sysfs_init(void)
 {
-	subsystem_register(&module_subsys);
+	int ret;
+
+	ret = subsystem_register(&module_subsys);
+	if (ret < 0) {
+		printk(KERN_WARNING "%s (%d): subsystem_register error: %d\n",
+			__FILE__, __LINE__, ret);
+		return ret;
+	}
 
 	param_sysfs_builtin();
 
 	return 0;
 }
-__initcall(param_sysfs_init);
+subsys_initcall(param_sysfs_init);
 
 EXPORT_SYMBOL(param_set_byte);
 EXPORT_SYMBOL(param_get_byte);
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index d38d9ec..479b16b 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1393,25 +1393,13 @@
 	}
 }
 
-static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
-
-int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-		     struct timespec *rqtp, struct timespec __user *rmtp)
+static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
+			    struct timespec *rqtp, struct itimerspec *it)
 {
-	struct restart_block *restart_block =
-	    &current_thread_info()->restart_block;
 	struct k_itimer timer;
 	int error;
 
 	/*
-	 * Diagnose required errors first.
-	 */
-	if (CPUCLOCK_PERTHREAD(which_clock) &&
-	    (CPUCLOCK_PID(which_clock) == 0 ||
-	     CPUCLOCK_PID(which_clock) == current->pid))
-		return -EINVAL;
-
-	/*
 	 * Set up a temporary timer and then wait for it to go off.
 	 */
 	memset(&timer, 0, sizeof timer);
@@ -1422,11 +1410,12 @@
 	timer.it_process = current;
 	if (!error) {
 		static struct itimerspec zero_it;
-		struct itimerspec it = { .it_value = *rqtp,
-					 .it_interval = {} };
+
+		memset(it, 0, sizeof *it);
+		it->it_value = *rqtp;
 
 		spin_lock_irq(&timer.it_lock);
-		error = posix_cpu_timer_set(&timer, flags, &it, NULL);
+		error = posix_cpu_timer_set(&timer, flags, it, NULL);
 		if (error) {
 			spin_unlock_irq(&timer.it_lock);
 			return error;
@@ -1454,49 +1443,89 @@
 		 * We were interrupted by a signal.
 		 */
 		sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
-		posix_cpu_timer_set(&timer, 0, &zero_it, &it);
+		posix_cpu_timer_set(&timer, 0, &zero_it, it);
 		spin_unlock_irq(&timer.it_lock);
 
-		if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
+		if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
 			/*
 			 * It actually did fire already.
 			 */
 			return 0;
 		}
 
-		/*
-		 * Report back to the user the time still remaining.
-		 */
-		if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
-		    copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
-			return -EFAULT;
-
-		restart_block->fn = posix_cpu_clock_nanosleep_restart;
-		/* Caller already set restart_block->arg1 */
-		restart_block->arg0 = which_clock;
-		restart_block->arg1 = (unsigned long) rmtp;
-		restart_block->arg2 = rqtp->tv_sec;
-		restart_block->arg3 = rqtp->tv_nsec;
-
 		error = -ERESTART_RESTARTBLOCK;
 	}
 
 	return error;
 }
 
-static long
-posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+		     struct timespec *rqtp, struct timespec __user *rmtp)
+{
+	struct restart_block *restart_block =
+	    &current_thread_info()->restart_block;
+	struct itimerspec it;
+	int error;
+
+	/*
+	 * Diagnose required errors first.
+	 */
+	if (CPUCLOCK_PERTHREAD(which_clock) &&
+	    (CPUCLOCK_PID(which_clock) == 0 ||
+	     CPUCLOCK_PID(which_clock) == current->pid))
+		return -EINVAL;
+
+	error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
+
+	if (error == -ERESTART_RESTARTBLOCK) {
+
+	       	if (flags & TIMER_ABSTIME)
+			return -ERESTARTNOHAND;
+		/*
+	 	 * Report back to the user the time still remaining.
+	 	 */
+		if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+			return -EFAULT;
+
+		restart_block->fn = posix_cpu_nsleep_restart;
+		restart_block->arg0 = which_clock;
+		restart_block->arg1 = (unsigned long) rmtp;
+		restart_block->arg2 = rqtp->tv_sec;
+		restart_block->arg3 = rqtp->tv_nsec;
+	}
+	return error;
+}
+
+long posix_cpu_nsleep_restart(struct restart_block *restart_block)
 {
 	clockid_t which_clock = restart_block->arg0;
 	struct timespec __user *rmtp;
 	struct timespec t;
+	struct itimerspec it;
+	int error;
 
 	rmtp = (struct timespec __user *) restart_block->arg1;
 	t.tv_sec = restart_block->arg2;
 	t.tv_nsec = restart_block->arg3;
 
 	restart_block->fn = do_no_restart_syscall;
-	return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
+	error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
+
+	if (error == -ERESTART_RESTARTBLOCK) {
+		/*
+	 	 * Report back to the user the time still remaining.
+	 	 */
+		if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+			return -EFAULT;
+
+		restart_block->fn = posix_cpu_nsleep_restart;
+		restart_block->arg0 = which_clock;
+		restart_block->arg1 = (unsigned long) rmtp;
+		restart_block->arg2 = t.tv_sec;
+		restart_block->arg3 = t.tv_nsec;
+	}
+	return error;
+
 }
 
 
@@ -1524,6 +1553,10 @@
 {
 	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
 }
+static long process_cpu_nsleep_restart(struct restart_block *restart_block)
+{
+	return -EINVAL;
+}
 static int thread_cpu_clock_getres(const clockid_t which_clock,
 				   struct timespec *tp)
 {
@@ -1544,6 +1577,10 @@
 {
 	return -EINVAL;
 }
+static long thread_cpu_nsleep_restart(struct restart_block *restart_block)
+{
+	return -EINVAL;
+}
 
 static __init int init_posix_cpu_timers(void)
 {
@@ -1553,6 +1590,7 @@
 		.clock_set = do_posix_clock_nosettime,
 		.timer_create = process_cpu_timer_create,
 		.nsleep = process_cpu_nsleep,
+		.nsleep_restart = process_cpu_nsleep_restart,
 	};
 	struct k_clock thread = {
 		.clock_getres = thread_cpu_clock_getres,
@@ -1560,6 +1598,7 @@
 		.clock_set = do_posix_clock_nosettime,
 		.timer_create = thread_cpu_timer_create,
 		.nsleep = thread_cpu_nsleep,
+		.nsleep_restart = thread_cpu_nsleep_restart,
 	};
 
 	register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index ac6dc87..e5ebcc1 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -973,3 +973,24 @@
 	return CLOCK_DISPATCH(which_clock, nsleep,
 			      (which_clock, flags, &t, rmtp));
 }
+
+/*
+ * nanosleep_restart for monotonic and realtime clocks
+ */
+static int common_nsleep_restart(struct restart_block *restart_block)
+{
+	return hrtimer_nanosleep_restart(restart_block);
+}
+
+/*
+ * This will restart clock_nanosleep. This is required only by
+ * compat_clock_nanosleep_restart for now.
+ */
+long
+clock_nanosleep_restart(struct restart_block *restart_block)
+{
+	clockid_t which_clock = restart_block->arg0;
+
+	return CLOCK_DISPATCH(which_clock, nsleep_restart,
+			      (restart_block));
+}
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 8aad033..4d50e06 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -440,6 +440,7 @@
 	child = find_task_by_pid(pid);
 	if (child)
 		get_task_struct(child);
+
 	read_unlock(&tasklist_lock);
 	if (!child)
 		return ERR_PTR(-ESRCH);
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 4d1c3d2..4f2c427 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -192,13 +192,13 @@
  * Definitions for rcu torture testing.
  */
 
-static int rcu_torture_read_lock(void)
+static int rcu_torture_read_lock(void) __acquires(RCU)
 {
 	rcu_read_lock();
 	return 0;
 }
 
-static void rcu_torture_read_unlock(int idx)
+static void rcu_torture_read_unlock(int idx) __releases(RCU)
 {
 	rcu_read_unlock();
 }
@@ -250,13 +250,13 @@
  * Definitions for rcu_bh torture testing.
  */
 
-static int rcu_bh_torture_read_lock(void)
+static int rcu_bh_torture_read_lock(void) __acquires(RCU_BH)
 {
 	rcu_read_lock_bh();
 	return 0;
 }
 
-static void rcu_bh_torture_read_unlock(int idx)
+static void rcu_bh_torture_read_unlock(int idx) __releases(RCU_BH)
 {
 	rcu_read_unlock_bh();
 }
diff --git a/kernel/relay.c b/kernel/relay.c
index 85786ff..1d63ecd 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -95,7 +95,7 @@
  *	@buf: the buffer struct
  *	@size: total size of the buffer
  *
- *	Returns a pointer to the resulting buffer, NULL if unsuccessful. The
+ *	Returns a pointer to the resulting buffer, %NULL if unsuccessful. The
  *	passed in size will get page aligned, if it isn't already.
  */
 static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
@@ -132,10 +132,9 @@
 
 /**
  *	relay_create_buf - allocate and initialize a channel buffer
- *	@alloc_size: size of the buffer to allocate
- *	@n_subbufs: number of sub-buffers in the channel
+ *	@chan: the relay channel
  *
- *	Returns channel buffer if successful, NULL otherwise
+ *	Returns channel buffer if successful, %NULL otherwise.
  */
 struct rchan_buf *relay_create_buf(struct rchan *chan)
 {
@@ -163,6 +162,7 @@
 
 /**
  *	relay_destroy_channel - free the channel struct
+ *	@kref: target kernel reference that contains the relay channel
  *
  *	Should only be called from kref_put().
  */
@@ -194,6 +194,7 @@
 
 /**
  *	relay_remove_buf - remove a channel buffer
+ *	@kref: target kernel reference that contains the relay buffer
  *
  *	Removes the file from the fileystem, which also frees the
  *	rchan_buf_struct and the channel buffer.  Should only be called from
@@ -374,7 +375,7 @@
 }
 EXPORT_SYMBOL_GPL(relay_reset);
 
-/**
+/*
  *	relay_open_buf - create a new relay channel buffer
  *
  *	Internal - used by relay_open().
@@ -448,12 +449,12 @@
 /**
  *	relay_open - create a new relay channel
  *	@base_filename: base name of files to create
- *	@parent: dentry of parent directory, NULL for root directory
+ *	@parent: dentry of parent directory, %NULL for root directory
  *	@subbuf_size: size of sub-buffers
  *	@n_subbufs: number of sub-buffers
  *	@cb: client callback functions
  *
- *	Returns channel pointer if successful, NULL otherwise.
+ *	Returns channel pointer if successful, %NULL otherwise.
  *
  *	Creates a channel buffer for each cpu using the sizes and
  *	attributes specified.  The created channel buffer files
@@ -585,7 +586,7 @@
  *	subbufs_consumed should be the number of sub-buffers newly consumed,
  *	not the total consumed.
  *
- *	NOTE: kernel clients don't need to call this function if the channel
+ *	NOTE: Kernel clients don't need to call this function if the channel
  *	mode is 'overwrite'.
  */
 void relay_subbufs_consumed(struct rchan *chan,
@@ -641,7 +642,7 @@
  *	relay_flush - close the channel
  *	@chan: the channel
  *
- *	Flushes all channel buffers i.e. forces buffer switch.
+ *	Flushes all channel buffers, i.e. forces buffer switch.
  */
 void relay_flush(struct rchan *chan)
 {
@@ -729,7 +730,7 @@
 	return 0;
 }
 
-/**
+/*
  *	relay_file_read_consume - update the consumed count for the buffer
  */
 static void relay_file_read_consume(struct rchan_buf *buf,
@@ -756,7 +757,7 @@
 	}
 }
 
-/**
+/*
  *	relay_file_read_avail - boolean, are there unconsumed bytes available?
  */
 static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
@@ -793,6 +794,8 @@
 
 /**
  *	relay_file_read_subbuf_avail - return bytes available in sub-buffer
+ *	@read_pos: file read position
+ *	@buf: relay channel buffer
  */
 static size_t relay_file_read_subbuf_avail(size_t read_pos,
 					   struct rchan_buf *buf)
@@ -818,6 +821,8 @@
 
 /**
  *	relay_file_read_start_pos - find the first available byte to read
+ *	@read_pos: file read position
+ *	@buf: relay channel buffer
  *
  *	If the read_pos is in the middle of padding, return the
  *	position of the first actually available byte, otherwise
@@ -844,6 +849,9 @@
 
 /**
  *	relay_file_read_end_pos - return the new read position
+ *	@read_pos: file read position
+ *	@buf: relay channel buffer
+ *	@count: number of bytes to be read
  */
 static size_t relay_file_read_end_pos(struct rchan_buf *buf,
 				      size_t read_pos,
@@ -865,7 +873,7 @@
 	return end_pos;
 }
 
-/**
+/*
  *	subbuf_read_actor - read up to one subbuf's worth of data
  */
 static int subbuf_read_actor(size_t read_start,
@@ -890,7 +898,7 @@
 	return ret;
 }
 
-/**
+/*
  *	subbuf_send_actor - send up to one subbuf's worth of data
  */
 static int subbuf_send_actor(size_t read_start,
@@ -933,7 +941,7 @@
 			       read_descriptor_t *desc,
 			       read_actor_t actor);
 
-/**
+/*
  *	relay_file_read_subbufs - read count bytes, bridging subbuf boundaries
  */
 static inline ssize_t relay_file_read_subbufs(struct file *filp,
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 3e13a1e..4ab17da 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -251,6 +251,7 @@
 
 	/* Grab the next task */
 	task = rt_mutex_owner(lock);
+	get_task_struct(task);
 	spin_lock_irqsave(&task->pi_lock, flags);
 
 	if (waiter == rt_mutex_top_waiter(lock)) {
@@ -269,7 +270,6 @@
 		__rt_mutex_adjust_prio(task);
 	}
 
-	get_task_struct(task);
 	spin_unlock_irqrestore(&task->pi_lock, flags);
 
 	top_waiter = rt_mutex_top_waiter(lock);
@@ -409,7 +409,7 @@
 	struct task_struct *owner = rt_mutex_owner(lock);
 	struct rt_mutex_waiter *top_waiter = waiter;
 	unsigned long flags;
-	int boost = 0, res;
+	int chain_walk = 0, res;
 
 	spin_lock_irqsave(&current->pi_lock, flags);
 	__rt_mutex_adjust_prio(current);
@@ -433,25 +433,23 @@
 		plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
 
 		__rt_mutex_adjust_prio(owner);
-		if (owner->pi_blocked_on) {
-			boost = 1;
-			/* gets dropped in rt_mutex_adjust_prio_chain()! */
-			get_task_struct(owner);
-		}
+		if (owner->pi_blocked_on)
+			chain_walk = 1;
 		spin_unlock_irqrestore(&owner->pi_lock, flags);
 	}
-	else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) {
-		spin_lock_irqsave(&owner->pi_lock, flags);
-		if (owner->pi_blocked_on) {
-			boost = 1;
-			/* gets dropped in rt_mutex_adjust_prio_chain()! */
-			get_task_struct(owner);
-		}
-		spin_unlock_irqrestore(&owner->pi_lock, flags);
-	}
-	if (!boost)
+	else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock))
+		chain_walk = 1;
+
+	if (!chain_walk)
 		return 0;
 
+	/*
+	 * The owner can't disappear while holding a lock,
+	 * so the owner struct is protected by wait_lock.
+	 * Gets dropped in rt_mutex_adjust_prio_chain()!
+	 */
+	get_task_struct(owner);
+
 	spin_unlock(&lock->wait_lock);
 
 	res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter,
@@ -532,7 +530,7 @@
 	int first = (waiter == rt_mutex_top_waiter(lock));
 	struct task_struct *owner = rt_mutex_owner(lock);
 	unsigned long flags;
-	int boost = 0;
+	int chain_walk = 0;
 
 	spin_lock_irqsave(&current->pi_lock, flags);
 	plist_del(&waiter->list_entry, &lock->wait_list);
@@ -554,19 +552,20 @@
 		}
 		__rt_mutex_adjust_prio(owner);
 
-		if (owner->pi_blocked_on) {
-			boost = 1;
-			/* gets dropped in rt_mutex_adjust_prio_chain()! */
-			get_task_struct(owner);
-		}
+		if (owner->pi_blocked_on)
+			chain_walk = 1;
+
 		spin_unlock_irqrestore(&owner->pi_lock, flags);
 	}
 
 	WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
 
-	if (!boost)
+	if (!chain_walk)
 		return;
 
+	/* gets dropped in rt_mutex_adjust_prio_chain()! */
+	get_task_struct(owner);
+
 	spin_unlock(&lock->wait_lock);
 
 	rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current);
@@ -592,10 +591,10 @@
 		return;
 	}
 
-	/* gets dropped in rt_mutex_adjust_prio_chain()! */
-	get_task_struct(task);
 	spin_unlock_irqrestore(&task->pi_lock, flags);
 
+	/* gets dropped in rt_mutex_adjust_prio_chain()! */
+	get_task_struct(task);
 	rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task);
 }
 
diff --git a/kernel/sched.c b/kernel/sched.c
index 5c848fd..74f169a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1755,27 +1755,27 @@
 	__releases(rq->lock)
 {
 	struct mm_struct *mm = rq->prev_mm;
-	unsigned long prev_task_flags;
+	long prev_state;
 
 	rq->prev_mm = NULL;
 
 	/*
 	 * A task struct has one reference for the use as "current".
-	 * If a task dies, then it sets EXIT_ZOMBIE in tsk->exit_state and
-	 * calls schedule one last time. The schedule call will never return,
-	 * and the scheduled task must drop that reference.
-	 * The test for EXIT_ZOMBIE must occur while the runqueue locks are
+	 * If a task dies, then it sets TASK_DEAD in tsk->state and calls
+	 * schedule one last time. The schedule call will never return, and
+	 * the scheduled task must drop that reference.
+	 * The test for TASK_DEAD must occur while the runqueue locks are
 	 * still held, otherwise prev could be scheduled on another cpu, die
 	 * there before we look at prev->state, and then the reference would
 	 * be dropped twice.
 	 *		Manfred Spraul <manfred@colorfullife.com>
 	 */
-	prev_task_flags = prev->flags;
+	prev_state = prev->state;
 	finish_arch_switch(prev);
 	finish_lock_switch(rq, prev);
 	if (mm)
 		mmdrop(mm);
-	if (unlikely(prev_task_flags & PF_DEAD)) {
+	if (unlikely(prev_state == TASK_DEAD)) {
 		/*
 		 * Remove function-return probe instances associated with this
 		 * task and put them back on the free list.
@@ -3348,9 +3348,6 @@
 
 	spin_lock_irq(&rq->lock);
 
-	if (unlikely(prev->flags & PF_DEAD))
-		prev->state = EXIT_DEAD;
-
 	switch_count = &prev->nivcsw;
 	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
 		switch_count = &prev->nvcsw;
@@ -4080,6 +4077,8 @@
  * @p: the task in question.
  * @policy: new policy.
  * @param: structure containing the new RT priority.
+ *
+ * NOTE: the task may be already dead
  */
 int sched_setscheduler(struct task_struct *p, int policy,
 		       struct sched_param *param)
@@ -4107,28 +4106,32 @@
 	    (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
 	    (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
 		return -EINVAL;
-	if ((policy == SCHED_NORMAL || policy == SCHED_BATCH)
-					!= (param->sched_priority == 0))
+	if (is_rt_policy(policy) != (param->sched_priority != 0))
 		return -EINVAL;
 
 	/*
 	 * Allow unprivileged RT tasks to decrease priority:
 	 */
 	if (!capable(CAP_SYS_NICE)) {
-		/*
-		 * can't change policy, except between SCHED_NORMAL
-		 * and SCHED_BATCH:
-		 */
-		if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) &&
-			(policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) &&
-				!p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
-			return -EPERM;
-		/* can't increase priority */
-		if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) &&
-		    param->sched_priority > p->rt_priority &&
-		    param->sched_priority >
-				p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
-			return -EPERM;
+		if (is_rt_policy(policy)) {
+			unsigned long rlim_rtprio;
+			unsigned long flags;
+
+			if (!lock_task_sighand(p, &flags))
+				return -ESRCH;
+			rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
+			unlock_task_sighand(p, &flags);
+
+			/* can't set/change the rt policy */
+			if (policy != p->policy && !rlim_rtprio)
+				return -EPERM;
+
+			/* can't increase priority */
+			if (param->sched_priority > p->rt_priority &&
+			    param->sched_priority > rlim_rtprio)
+				return -EPERM;
+		}
+
 		/* can't change other user's priorities */
 		if ((current->euid != p->euid) &&
 		    (current->euid != p->uid))
@@ -4193,14 +4196,13 @@
 		return -EINVAL;
 	if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
 		return -EFAULT;
-	read_lock_irq(&tasklist_lock);
+
+	rcu_read_lock();
+	retval = -ESRCH;
 	p = find_process_by_pid(pid);
-	if (!p) {
-		read_unlock_irq(&tasklist_lock);
-		return -ESRCH;
-	}
-	retval = sched_setscheduler(p, policy, &lparam);
-	read_unlock_irq(&tasklist_lock);
+	if (p != NULL)
+		retval = sched_setscheduler(p, policy, &lparam);
+	rcu_read_unlock();
 
 	return retval;
 }
@@ -5151,7 +5153,7 @@
 	BUG_ON(p->exit_state != EXIT_ZOMBIE && p->exit_state != EXIT_DEAD);
 
 	/* Cannot have done final schedule yet: would have vanished. */
-	BUG_ON(p->flags & PF_DEAD);
+	BUG_ON(p->state == TASK_DEAD);
 
 	get_task_struct(p);
 
@@ -5272,9 +5274,11 @@
 int __init migration_init(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
+	int err;
 
 	/* Start one for the boot CPU: */
-	migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);
+	err = migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);
+	BUG_ON(err == NOTIFY_BAD);
 	migration_call(&migration_notifier, CPU_ONLINE, cpu);
 	register_cpu_notifier(&migration_notifier);
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 05853a7..fb5da6d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -417,9 +417,8 @@
 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
 			siginfo_t *info)
 {
-	int sig = 0;
+	int sig = next_signal(pending, mask);
 
-	sig = next_signal(pending, mask);
 	if (sig) {
 		if (current->notifier) {
 			if (sigismember(current->notifier_mask, sig)) {
@@ -432,9 +431,7 @@
 
 		if (!collect_signal(sig, pending, info))
 			sig = 0;
-				
 	}
-	recalc_sigpending();
 
 	return sig;
 }
@@ -451,6 +448,7 @@
 	if (!signr)
 		signr = __dequeue_signal(&tsk->signal->shared_pending,
 					 mask, info);
+	recalc_sigpending_tsk(tsk);
  	if (signr && unlikely(sig_kernel_stop(signr))) {
  		/*
  		 * Set a marker that we have dequeued a stop signal.  Our
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 3789ca9..bf25015 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -612,7 +612,9 @@
 __init int spawn_ksoftirqd(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
-	cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+	int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+
+	BUG_ON(err == NOTIFY_BAD);
 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
 	register_cpu_notifier(&cpu_nfb);
 	return 0;
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 03e6a2b..50afeb8 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -149,8 +149,9 @@
 __init void spawn_softlockup_task(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
+	int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
 
-	cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+	BUG_ON(err == NOTIFY_BAD);
 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
 	register_cpu_notifier(&cpu_nfb);
 
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index 9644a41..d48143e 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -21,17 +21,6 @@
 #include <linux/debug_locks.h>
 #include <linux/module.h>
 
-/*
- * Generic declaration of the raw read_trylock() function,
- * architectures are supposed to optimize this:
- */
-int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock)
-{
-	__raw_read_lock(lock);
-	return 1;
-}
-EXPORT_SYMBOL(generic__raw_read_trylock);
-
 int __lockfunc _spin_trylock(spinlock_t *lock)
 {
 	preempt_disable();
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 51cacd1..1245804 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -1,3 +1,6 @@
+/* Copyright 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation.
+ * GPL v2 and any later version.
+ */
 #include <linux/stop_machine.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
diff --git a/kernel/sys.c b/kernel/sys.c
index 3f89477..8647061 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -612,7 +612,6 @@
 	} else {
 		printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);
 	}
-	printk(".\n");
 	machine_restart(cmd);
 }
 EXPORT_SYMBOL_GPL(kernel_restart);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8bfa7d1..9535a38 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1915,7 +1915,7 @@
 		return -EPERM;
 	}
 
-	op = (current->pid == 1) ? OP_SET : OP_AND;
+	op = is_init(current) ? OP_SET : OP_AND;
 	return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
 				do_proc_dointvec_bset_conv,&op);
 }
diff --git a/kernel/timer.c b/kernel/timer.c
index 1d7dd62..4f55622 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -136,7 +136,7 @@
 	list_add_tail(&timer->entry, vec);
 }
 
-/***
+/**
  * init_timer - initialize a timer.
  * @timer: the timer to be initialized
  *
@@ -175,6 +175,7 @@
  */
 static tvec_base_t *lock_timer_base(struct timer_list *timer,
 					unsigned long *flags)
+	__acquires(timer->base->lock)
 {
 	tvec_base_t *base;
 
@@ -235,7 +236,7 @@
 
 EXPORT_SYMBOL(__mod_timer);
 
-/***
+/**
  * add_timer_on - start a timer on a particular CPU
  * @timer: the timer to be added
  * @cpu: the CPU to start it on
@@ -255,9 +256,10 @@
 }
 
 
-/***
+/**
  * mod_timer - modify a timer's timeout
  * @timer: the timer to be modified
+ * @expires: new timeout in jiffies
  *
  * mod_timer is a more efficient way to update the expire field of an
  * active timer (if the timer is inactive it will be activated)
@@ -291,7 +293,7 @@
 
 EXPORT_SYMBOL(mod_timer);
 
-/***
+/**
  * del_timer - deactive a timer.
  * @timer: the timer to be deactivated
  *
@@ -323,7 +325,10 @@
 EXPORT_SYMBOL(del_timer);
 
 #ifdef CONFIG_SMP
-/*
+/**
+ * try_to_del_timer_sync - Try to deactivate a timer
+ * @timer: timer do del
+ *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.
  *
@@ -351,7 +356,7 @@
 	return ret;
 }
 
-/***
+/**
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
  *
@@ -401,15 +406,15 @@
 	return index;
 }
 
-/***
+#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
+
+/**
  * __run_timers - run all expired timers (if any) on this CPU.
  * @base: the timer vector to be processed.
  *
  * This function cascades all vectors and executes all expired timer
  * vectors.
  */
-#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
-
 static inline void __run_timers(tvec_base_t *base)
 {
 	struct timer_list *timer;
@@ -970,7 +975,7 @@
 
 
 static int timekeeping_suspended;
-/*
+/**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  * @dev:	unused
  *
@@ -1106,7 +1111,7 @@
 	clock->error -= (interval - offset) << (TICK_LENGTH_SHIFT - clock->shift);
 }
 
-/*
+/**
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
  * Called from the timer interrupt, must hold a write on xtime_lock.
@@ -1217,10 +1222,8 @@
 	unsigned long active_tasks; /* fixed-point */
 	static int count = LOAD_FREQ;
 
-	count -= ticks;
-	if (count < 0) {
-		count += LOAD_FREQ;
-		active_tasks = count_active_tasks();
+	active_tasks = count_active_tasks();
+	for (count -= ticks; count < 0; count += LOAD_FREQ) {
 		CALC_LOAD(avenrun[0], EXP_1, active_tasks);
 		CALC_LOAD(avenrun[1], EXP_5, active_tasks);
 		CALC_LOAD(avenrun[2], EXP_15, active_tasks);
@@ -1265,11 +1268,8 @@
  * Called by the timer interrupt. xtime_lock must already be taken
  * by the timer IRQ!
  */
-static inline void update_times(void)
+static inline void update_times(unsigned long ticks)
 {
-	unsigned long ticks;
-
-	ticks = jiffies - wall_jiffies;
 	wall_jiffies += ticks;
 	update_wall_time();
 	calc_load(ticks);
@@ -1281,12 +1281,10 @@
  * jiffies is defined in the linker script...
  */
 
-void do_timer(struct pt_regs *regs)
+void do_timer(unsigned long ticks)
 {
-	jiffies_64++;
-	/* prevent loading jiffies before storing new jiffies_64 value. */
-	barrier();
-	update_times();
+	jiffies_64 += ticks;
+	update_times(ticks);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
@@ -1470,8 +1468,9 @@
 	return current->pid;
 }
 
-/*
+/**
  * sys_sysinfo - fill in sysinfo struct
+ * @info: pointer to buffer to fill
  */ 
 asmlinkage long sys_sysinfo(struct sysinfo __user *info)
 {
@@ -1688,8 +1687,10 @@
 
 void __init init_timers(void)
 {
-	timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
+	int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
 				(void *)(long)smp_processor_id());
+
+	BUG_ON(err == NOTIFY_BAD);
 	register_cpu_notifier(&timers_nb);
 	open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
 }
diff --git a/kernel/unwind.c b/kernel/unwind.c
index 3430475..2e23686 100644
--- a/kernel/unwind.c
+++ b/kernel/unwind.c
@@ -102,7 +102,7 @@
 	unsigned long size;
 	struct unwind_table *link;
 	const char *name;
-} root_table, *last_table;
+} root_table;
 
 struct unwind_item {
 	enum item_location {
@@ -174,6 +174,8 @@
 
 #ifdef CONFIG_MODULES
 
+static struct unwind_table *last_table;
+
 /* Must be called with module_mutex held. */
 void *unwind_add_table(struct module *module,
                        const void *table_start,
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b0f5ca7..f9ae75c 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -320,6 +320,15 @@
 
 	  If unsure, say N.
 
+config DEBUG_LIST
+	bool "Debug linked list manipulation"
+	depends on DEBUG_KERNEL
+	help
+	  Enable this to turn on extended checks in the linked-list
+	  walking routines.
+
+	  If unsure, say N.
+
 config FRAME_POINTER
 	bool "Compile the kernel with frame pointers"
 	depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH)
diff --git a/lib/Makefile b/lib/Makefile
index ef1d37a..402762fe 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -28,6 +28,7 @@
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 obj-$(CONFIG_PLIST) += plist.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
+obj-$(CONFIG_DEBUG_LIST) += list_debug.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
   lib-y += dec_and_lock.o
diff --git a/lib/list_debug.c b/lib/list_debug.c
new file mode 100644
index 0000000..e80d27c
--- /dev/null
+++ b/lib/list_debug.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2006, Red Hat, Inc., Dave Jones
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the linked list implementations for
+ * DEBUG_LIST.
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+
+void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	if (unlikely(next->prev != prev)) {
+		printk(KERN_ERR "list_add corruption. next->prev should be %p, but was %p\n",
+			prev, next->prev);
+		BUG();
+	}
+	if (unlikely(prev->next != next)) {
+		printk(KERN_ERR "list_add corruption. prev->next should be %p, but was %p\n",
+			next, prev->next);
+		BUG();
+	}
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+EXPORT_SYMBOL(__list_add);
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+EXPORT_SYMBOL(list_add);
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+void list_del(struct list_head *entry)
+{
+	BUG_ON(entry->prev->next != entry);
+	BUG_ON(entry->next->prev != entry);
+
+	if (unlikely(entry->prev->next != entry)) {
+		printk(KERN_ERR "list_del corruption. prev->next should be %p, "
+				"but was %p\n", entry, entry->prev->next);
+		BUG();
+	}
+	if (unlikely(entry->next->prev != entry)) {
+		printk(KERN_ERR "list_del corruption. next->prev should be %p, "
+				"but was %p\n", entry, entry->next->prev);
+		BUG();
+	}
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+EXPORT_SYMBOL(list_del);
diff --git a/lib/rwsem.c b/lib/rwsem.c
index b322421..901d0e7 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -146,7 +146,7 @@
 /*
  * wait for a lock to be granted
  */
-static inline struct rw_semaphore *
+static struct rw_semaphore *
 rwsem_down_failed_common(struct rw_semaphore *sem,
 			struct rwsem_waiter *waiter, signed long adjustment)
 {
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 58c577d..dafaf1d 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -99,11 +99,12 @@
 
 static void __spin_lock_debug(spinlock_t *lock)
 {
-	int print_once = 1;
 	u64 i;
+	u64 loops = loops_per_jiffy * HZ;
+	int print_once = 1;
 
 	for (;;) {
-		for (i = 0; i < loops_per_jiffy * HZ; i++) {
+		for (i = 0; i < loops; i++) {
 			if (__raw_spin_trylock(&lock->raw_lock))
 				return;
 			__delay(1);
@@ -165,11 +166,12 @@
 #if 0		/* __write_lock_debug() can lock up - maybe this can too? */
 static void __read_lock_debug(rwlock_t *lock)
 {
-	int print_once = 1;
 	u64 i;
+	u64 loops = loops_per_jiffy * HZ;
+	int print_once = 1;
 
 	for (;;) {
-		for (i = 0; i < loops_per_jiffy * HZ; i++) {
+		for (i = 0; i < loops; i++) {
 			if (__raw_read_trylock(&lock->raw_lock))
 				return;
 			__delay(1);
@@ -239,11 +241,12 @@
 #if 0		/* This can cause lockups */
 static void __write_lock_debug(rwlock_t *lock)
 {
-	int print_once = 1;
 	u64 i;
+	u64 loops = loops_per_jiffy * HZ;
+	int print_once = 1;
 
 	for (;;) {
-		for (i = 0; i < loops_per_jiffy * HZ; i++) {
+		for (i = 0; i < loops; i++) {
 			if (__raw_write_trylock(&lock->raw_lock))
 				return;
 			__delay(1);
diff --git a/lib/ts_fsm.c b/lib/ts_fsm.c
index 87847c2..af575b6 100644
--- a/lib/ts_fsm.c
+++ b/lib/ts_fsm.c
@@ -12,13 +12,13 @@
  *
  *   A finite state machine consists of n states (struct ts_fsm_token)
  *   representing the pattern as a finite automation. The data is read
- *   sequentially on a octet basis. Every state token specifies the number
+ *   sequentially on an octet basis. Every state token specifies the number
  *   of recurrences and the type of value accepted which can be either a
  *   specific character or ctype based set of characters. The available
  *   type of recurrences include 1, (0|1), [0 n], and [1 n].
  *
- *   The algorithm differs between strict/non-strict mode specyfing
- *   whether the pattern has to start at the first octect. Strict mode
+ *   The algorithm differs between strict/non-strict mode specifying
+ *   whether the pattern has to start at the first octet. Strict mode
  *   is enabled by default and can be disabled by inserting
  *   TS_FSM_HEAD_IGNORE as the first token in the chain.
  *
@@ -44,7 +44,7 @@
 #define _W		0x200 /* wildcard */
 
 /* Map to _ctype flags and some magic numbers */
-static u16 token_map[TS_FSM_TYPE_MAX+1] = {
+static const u16 token_map[TS_FSM_TYPE_MAX+1] = {
 	[TS_FSM_SPECIFIC] = 0,
 	[TS_FSM_WILDCARD] = _W,
 	[TS_FSM_CNTRL]	  = _C,
@@ -61,7 +61,7 @@
 	[TS_FSM_ASCII]	  = _A,
 };
 
-static u16 token_lookup_tbl[256] = {
+static const u16 token_lookup_tbl[256] = {
 _W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*   0-  3 */
 _W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*   4-  7 */
 _W|_A|_C,      _W|_A|_C|_S,  _W|_A|_C|_S,  _W|_A|_C|_S,		/*   8- 11 */
diff --git a/mm/Makefile b/mm/Makefile
index 60c56c0..6200c6d 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -17,6 +17,7 @@
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SHMEM) += shmem.o
+obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
 obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
 obj-$(CONFIG_SLOB) += slob.o
 obj-$(CONFIG_SLAB) += slab.o
diff --git a/mm/filemap.c b/mm/filemap.c
index afcdc72..3277f3b 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1471,7 +1471,7 @@
 	 * accessible..
 	 */
 	if (area->vm_mm == current->mm)
-		return NULL;
+		return NOPAGE_SIGBUS;
 	/* Fall through to the non-read-ahead case */
 no_cached_page:
 	/*
@@ -1496,7 +1496,7 @@
 	 */
 	if (error == -ENOMEM)
 		return NOPAGE_OOM;
-	return NULL;
+	return NOPAGE_SIGBUS;
 
 page_not_uptodate:
 	if (!did_readaround) {
@@ -1565,7 +1565,7 @@
 	 */
 	shrink_readahead_size_eio(file, ra);
 	page_cache_release(page);
-	return NULL;
+	return NOPAGE_SIGBUS;
 }
 EXPORT_SYMBOL(filemap_nopage);
 
diff --git a/mm/memory.c b/mm/memory.c
index 601159a..160f5b5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1577,7 +1577,14 @@
 		entry = mk_pte(new_page, vma->vm_page_prot);
 		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 		lazy_mmu_prot_update(entry);
-		ptep_establish(vma, address, page_table, entry);
+		/*
+		 * Clear the pte entry and flush it first, before updating the
+		 * pte with the new entry. This will avoid a race condition
+		 * seen in the presence of one thread doing SMC and another
+		 * thread doing COW.
+		 */
+		ptep_clear_flush(vma, address, page_table);
+		set_pte_at(mm, address, page_table, entry);
 		update_mmu_cache(vma, address, entry);
 		lru_cache_add_active(new_page);
 		page_add_new_anon_rmap(new_page, vma, address);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index c373195..2053bb1 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/pagevec.h>
+#include <linux/writeback.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
@@ -21,6 +22,7 @@
 #include <linux/highmem.h>
 #include <linux/vmalloc.h>
 #include <linux/ioport.h>
+#include <linux/cpuset.h>
 
 #include <asm/tlbflush.h>
 
@@ -191,6 +193,7 @@
 	if (need_zonelists_rebuild)
 		build_all_zonelists();
 	vm_total_pages = nr_free_pagecache_pages();
+	writeback_set_ratelimit();
 	return 0;
 }
 
@@ -283,6 +286,8 @@
 	/* we online node here. we can't roll back from here. */
 	node_set_online(nid);
 
+	cpuset_track_online_nodes();
+
 	if (new_pgdat) {
 		ret = register_one_node(nid);
 		/*
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index bada3d0..20f41b0 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -204,16 +204,30 @@
 	do_posix_clock_monotonic_gettime(&uptime);
 	do_each_thread(g, p) {
 		unsigned long points;
-		int releasing;
 
-		/* skip kernel threads */
+		/*
+		 * skip kernel threads and tasks which have already released
+		 * their mm.
+		 */
 		if (!p->mm)
 			continue;
-		/* skip the init task with pid == 1 */
-		if (p->pid == 1)
+		/* skip the init task */
+		if (is_init(p))
 			continue;
 
 		/*
+		 * This task already has access to memory reserves and is
+		 * being killed. Don't allow any other task access to the
+		 * memory reserve.
+		 *
+		 * Note: this may have a chance of deadlock if it gets
+		 * blocked waiting for another task which itself is waiting
+		 * for memory. Is there a better alternative?
+		 */
+		if (test_tsk_thread_flag(p, TIF_MEMDIE))
+			return ERR_PTR(-1UL);
+
+		/*
 		 * This is in the process of releasing memory so wait for it
 		 * to finish before killing some other task by mistake.
 		 *
@@ -221,21 +235,16 @@
 		 * go ahead if it is exiting: this will simply set TIF_MEMDIE,
 		 * which will allow it to gain access to memory reserves in
 		 * the process of exiting and releasing its resources.
-		 * Otherwise we could get an OOM deadlock.
+		 * Otherwise we could get an easy OOM deadlock.
 		 */
-		releasing = test_tsk_thread_flag(p, TIF_MEMDIE) ||
-						p->flags & PF_EXITING;
-		if (releasing) {
-			/* PF_DEAD tasks have already released their mm */
-			if (p->flags & PF_DEAD)
-				continue;
-			if (p->flags & PF_EXITING && p == current) {
-				chosen = p;
-				*ppoints = ULONG_MAX;
-				break;
-			}
-			return ERR_PTR(-1UL);
+		if (p->flags & PF_EXITING) {
+			if (p != current)
+				return ERR_PTR(-1UL);
+
+			chosen = p;
+			*ppoints = ULONG_MAX;
 		}
+
 		if (p->oomkilladj == OOM_DISABLE)
 			continue;
 
@@ -245,6 +254,7 @@
 			*ppoints = points;
 		}
 	} while_each_thread(g, p);
+
 	return chosen;
 }
 
@@ -255,20 +265,17 @@
  */
 static void __oom_kill_task(struct task_struct *p, const char *message)
 {
-	if (p->pid == 1) {
+	if (is_init(p)) {
 		WARN_ON(1);
 		printk(KERN_WARNING "tried to kill init!\n");
 		return;
 	}
 
-	task_lock(p);
-	if (!p->mm || p->mm == &init_mm) {
+	if (!p->mm) {
 		WARN_ON(1);
 		printk(KERN_WARNING "tried to kill an mm-less task!\n");
-		task_unlock(p);
 		return;
 	}
-	task_unlock(p);
 
 	if (message) {
 		printk(KERN_ERR "%s: Killed process %d (%s).\n",
@@ -302,7 +309,7 @@
 	 * However, this is of no concern to us.
 	 */
 
-	if (mm == NULL || mm == &init_mm)
+	if (mm == NULL)
 		return 1;
 
 	__oom_kill_task(p, message);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 5557529..488b708 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -46,7 +46,6 @@
  */
 static long ratelimit_pages = 32;
 
-static long total_pages;	/* The total number of pages in the machine. */
 static int dirty_exceeded __cacheline_aligned_in_smp;	/* Dirty mem may be over limit */
 
 /*
@@ -126,7 +125,7 @@
 	int unmapped_ratio;
 	long background;
 	long dirty;
-	unsigned long available_memory = total_pages;
+	unsigned long available_memory = vm_total_pages;
 	struct task_struct *tsk;
 
 #ifdef CONFIG_HIGHMEM
@@ -141,7 +140,7 @@
 
 	unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) +
 				global_page_state(NR_ANON_PAGES)) * 100) /
-					total_pages;
+					vm_total_pages;
 
 	dirty_ratio = vm_dirty_ratio;
 	if (dirty_ratio > unmapped_ratio / 2)
@@ -502,9 +501,9 @@
  * will write six megabyte chunks, max.
  */
 
-static void set_ratelimit(void)
+void writeback_set_ratelimit(void)
 {
-	ratelimit_pages = total_pages / (num_online_cpus() * 32);
+	ratelimit_pages = vm_total_pages / (num_online_cpus() * 32);
 	if (ratelimit_pages < 16)
 		ratelimit_pages = 16;
 	if (ratelimit_pages * PAGE_CACHE_SIZE > 4096 * 1024)
@@ -514,7 +513,7 @@
 static int __cpuinit
 ratelimit_handler(struct notifier_block *self, unsigned long u, void *v)
 {
-	set_ratelimit();
+	writeback_set_ratelimit();
 	return 0;
 }
 
@@ -533,9 +532,7 @@
 	long buffer_pages = nr_free_buffer_pages();
 	long correction;
 
-	total_pages = nr_free_pagecache_pages();
-
-	correction = (100 * 4 * buffer_pages) / total_pages;
+	correction = (100 * 4 * buffer_pages) / vm_total_pages;
 
 	if (correction < 100) {
 		dirty_background_ratio *= correction;
@@ -549,7 +546,7 @@
 			vm_dirty_ratio = 1;
 	}
 	mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
-	set_ratelimit();
+	writeback_set_ratelimit();
 	register_cpu_notifier(&ratelimit_nb);
 }
 
diff --git a/mm/shmem.c b/mm/shmem.c
index eda907c..b96de69 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -26,6 +26,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/xattr.h>
+#include <linux/generic_acl.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/file.h>
@@ -177,6 +179,7 @@
 static struct file_operations shmem_file_operations;
 static struct inode_operations shmem_inode_operations;
 static struct inode_operations shmem_dir_inode_operations;
+static struct inode_operations shmem_special_inode_operations;
 static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
@@ -637,7 +640,7 @@
 	struct page *page = NULL;
 	int error;
 
-	if (attr->ia_valid & ATTR_SIZE) {
+	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
 		if (attr->ia_size < inode->i_size) {
 			/*
 			 * If truncating down to a partial page, then
@@ -670,6 +673,10 @@
 	error = inode_change_ok(inode, attr);
 	if (!error)
 		error = inode_setattr(inode, attr);
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	if (!error && (attr->ia_valid & ATTR_MODE))
+		error = generic_acl_chmod(inode, &shmem_acl_ops);
+#endif
 	if (page)
 		page_cache_release(page);
 	return error;
@@ -1362,6 +1369,7 @@
 
 		switch (mode & S_IFMT) {
 		default:
+			inode->i_op = &shmem_special_inode_operations;
 			init_special_inode(inode, mode, dev);
 			break;
 		case S_IFREG:
@@ -1682,7 +1690,11 @@
 				iput(inode);
 				return error;
 			}
-			error = 0;
+		}
+		error = shmem_acl_init(inode, dir);
+		if (error) {
+			iput(inode);
+			return error;
 		}
 		if (dir->i_mode & S_ISGID) {
 			inode->i_gid = dir->i_gid;
@@ -1897,6 +1909,53 @@
 	.put_link	= shmem_put_link,
 };
 
+#ifdef CONFIG_TMPFS_POSIX_ACL
+/**
+ * Superblocks without xattr inode operations will get security.* xattr
+ * support from the VFS "for free". As soon as we have any other xattrs
+ * like ACLs, we also need to implement the security.* handlers at
+ * filesystem level, though.
+ */
+
+static size_t shmem_xattr_security_list(struct inode *inode, char *list,
+					size_t list_len, const char *name,
+					size_t name_len)
+{
+	return security_inode_listsecurity(inode, list, list_len);
+}
+
+static int shmem_xattr_security_get(struct inode *inode, const char *name,
+				    void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return security_inode_getsecurity(inode, name, buffer, size,
+					  -EOPNOTSUPP);
+}
+
+static int shmem_xattr_security_set(struct inode *inode, const char *name,
+				    const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return security_inode_setsecurity(inode, name, value, size, flags);
+}
+
+struct xattr_handler shmem_xattr_security_handler = {
+	.prefix = XATTR_SECURITY_PREFIX,
+	.list   = shmem_xattr_security_list,
+	.get    = shmem_xattr_security_get,
+	.set    = shmem_xattr_security_set,
+};
+
+static struct xattr_handler *shmem_xattr_handlers[] = {
+	&shmem_xattr_acl_access_handler,
+	&shmem_xattr_acl_default_handler,
+	&shmem_xattr_security_handler,
+	NULL
+};
+#endif
+
 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)
@@ -2094,6 +2153,10 @@
 	sb->s_magic = TMPFS_MAGIC;
 	sb->s_op = &shmem_ops;
 	sb->s_time_gran = 1;
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	sb->s_xattr = shmem_xattr_handlers;
+	sb->s_flags |= MS_POSIXACL;
+#endif
 
 	inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
 	if (!inode)
@@ -2130,6 +2193,7 @@
 		/* only struct inode is valid if it's an inline symlink */
 		mpol_free_shared_policy(&SHMEM_I(inode)->policy);
 	}
+	shmem_acl_destroy_inode(inode);
 	kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
 }
 
@@ -2141,6 +2205,10 @@
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
 		inode_init_once(&p->vfs_inode);
+#ifdef CONFIG_TMPFS_POSIX_ACL
+		p->i_acl = NULL;
+		p->i_default_acl = NULL;
+#endif
 	}
 }
 
@@ -2184,6 +2252,14 @@
 	.truncate	= shmem_truncate,
 	.setattr	= shmem_notify_change,
 	.truncate_range	= shmem_truncate_range,
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= generic_listxattr,
+	.removexattr	= generic_removexattr,
+	.permission	= shmem_permission,
+#endif
+
 };
 
 static struct inode_operations shmem_dir_inode_operations = {
@@ -2198,6 +2274,25 @@
 	.mknod		= shmem_mknod,
 	.rename		= shmem_rename,
 #endif
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	.setattr	= shmem_notify_change,
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= generic_listxattr,
+	.removexattr	= generic_removexattr,
+	.permission	= shmem_permission,
+#endif
+};
+
+static struct inode_operations shmem_special_inode_operations = {
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	.setattr	= shmem_notify_change,
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= generic_listxattr,
+	.removexattr	= generic_removexattr,
+	.permission	= shmem_permission,
+#endif
 };
 
 static struct super_operations shmem_ops = {
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
new file mode 100644
index 0000000..c946bf4
--- /dev/null
+++ b/mm/shmem_acl.c
@@ -0,0 +1,197 @@
+/*
+ * mm/shmem_acl.c
+ *
+ * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/fs.h>
+#include <linux/shmem_fs.h>
+#include <linux/xattr.h>
+#include <linux/generic_acl.h>
+
+/**
+ * shmem_get_acl  -   generic_acl_operations->getacl() operation
+ */
+static struct posix_acl *
+shmem_get_acl(struct inode *inode, int type)
+{
+	struct posix_acl *acl = NULL;
+
+	spin_lock(&inode->i_lock);
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			acl = posix_acl_dup(SHMEM_I(inode)->i_acl);
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			acl = posix_acl_dup(SHMEM_I(inode)->i_default_acl);
+			break;
+	}
+	spin_unlock(&inode->i_lock);
+
+	return acl;
+}
+
+/**
+ * shmem_get_acl  -   generic_acl_operations->setacl() operation
+ */
+static void
+shmem_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	struct posix_acl *free = NULL;
+
+	spin_lock(&inode->i_lock);
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			free = SHMEM_I(inode)->i_acl;
+			SHMEM_I(inode)->i_acl = posix_acl_dup(acl);
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			free = SHMEM_I(inode)->i_default_acl;
+			SHMEM_I(inode)->i_default_acl = posix_acl_dup(acl);
+			break;
+	}
+	spin_unlock(&inode->i_lock);
+	posix_acl_release(free);
+}
+
+struct generic_acl_operations shmem_acl_ops = {
+	.getacl = shmem_get_acl,
+	.setacl = shmem_set_acl,
+};
+
+/**
+ * shmem_list_acl_access, shmem_get_acl_access, shmem_set_acl_access,
+ * shmem_xattr_acl_access_handler  -  plumbing code to implement the
+ * system.posix_acl_access xattr using the generic acl functions.
+ */
+
+static size_t
+shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
+		      const char *name, size_t name_len)
+{
+	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_ACCESS,
+				list, list_size);
+}
+
+static int
+shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
+		     size_t size)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, buffer,
+			       size);
+}
+
+static int
+shmem_set_acl_access(struct inode *inode, const char *name, const void *value,
+		     size_t size, int flags)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, value,
+			       size);
+}
+
+struct xattr_handler shmem_xattr_acl_access_handler = {
+	.prefix = POSIX_ACL_XATTR_ACCESS,
+	.list	= shmem_list_acl_access,
+	.get	= shmem_get_acl_access,
+	.set	= shmem_set_acl_access,
+};
+
+/**
+ * shmem_list_acl_default, shmem_get_acl_default, shmem_set_acl_default,
+ * shmem_xattr_acl_default_handler  -  plumbing code to implement the
+ * system.posix_acl_default xattr using the generic acl functions.
+ */
+
+static size_t
+shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
+		       const char *name, size_t name_len)
+{
+	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT,
+				list, list_size);
+}
+
+static int
+shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
+		      size_t size)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, buffer,
+			       size);
+}
+
+static int
+shmem_set_acl_default(struct inode *inode, const char *name, const void *value,
+		      size_t size, int flags)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, value,
+			       size);
+}
+
+struct xattr_handler shmem_xattr_acl_default_handler = {
+	.prefix = POSIX_ACL_XATTR_DEFAULT,
+	.list	= shmem_list_acl_default,
+	.get	= shmem_get_acl_default,
+	.set	= shmem_set_acl_default,
+};
+
+/**
+ * shmem_acl_init  -  Inizialize the acl(s) of a new inode
+ */
+int
+shmem_acl_init(struct inode *inode, struct inode *dir)
+{
+	return generic_acl_init(inode, dir, &shmem_acl_ops);
+}
+
+/**
+ * shmem_acl_destroy_inode  -  destroy acls hanging off the in-memory inode
+ *
+ * This is done before destroying the actual inode.
+ */
+
+void
+shmem_acl_destroy_inode(struct inode *inode)
+{
+	if (SHMEM_I(inode)->i_acl)
+		posix_acl_release(SHMEM_I(inode)->i_acl);
+	SHMEM_I(inode)->i_acl = NULL;
+	if (SHMEM_I(inode)->i_default_acl)
+		posix_acl_release(SHMEM_I(inode)->i_default_acl);
+	SHMEM_I(inode)->i_default_acl = NULL;
+}
+
+/**
+ * shmem_check_acl  -  check_acl() callback for generic_permission()
+ */
+static int
+shmem_check_acl(struct inode *inode, int mask)
+{
+	struct posix_acl *acl = shmem_get_acl(inode, ACL_TYPE_ACCESS);
+
+	if (acl) {
+		int error = posix_acl_permission(inode, acl, mask);
+		posix_acl_release(acl);
+		return error;
+	}
+	return -EAGAIN;
+}
+
+/**
+ * shmem_permission  -  permission() inode operation
+ */
+int
+shmem_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	return generic_permission(inode, mask, shmem_check_acl);
+}
diff --git a/mm/slab.c b/mm/slab.c
index 792bfe3..3dbd6f4 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1683,10 +1683,32 @@
 static void dump_line(char *data, int offset, int limit)
 {
 	int i;
+	unsigned char error = 0;
+	int bad_count = 0;
+
 	printk(KERN_ERR "%03x:", offset);
-	for (i = 0; i < limit; i++)
+	for (i = 0; i < limit; i++) {
+		if (data[offset + i] != POISON_FREE) {
+			error = data[offset + i];
+			bad_count++;
+		}
 		printk(" %02x", (unsigned char)data[offset + i]);
+	}
 	printk("\n");
+
+	if (bad_count == 1) {
+		error ^= POISON_FREE;
+		if (!(error & (error - 1))) {
+			printk(KERN_ERR "Single bit error detected. Probably "
+					"bad RAM.\n");
+#ifdef CONFIG_X86
+			printk(KERN_ERR "Run memtest86+ or a similar memory "
+					"test tool.\n");
+#else
+			printk(KERN_ERR "Run a memory test tool.\n");
+#endif
+		}
+	}
 }
 #endif
 
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f1f5ec7..a15def6 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1723,13 +1723,14 @@
  */
 int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
 {
-	int ret = 0, i = 1 << page_cluster;
+	int our_page_cluster = page_cluster;
+	int ret = 0, i = 1 << our_page_cluster;
 	unsigned long toff;
 	struct swap_info_struct *swapdev = swp_type(entry) + swap_info;
 
-	if (!page_cluster)	/* no readahead */
+	if (!our_page_cluster)	/* no readahead */
 		return 0;
-	toff = (swp_offset(entry) >> page_cluster) << page_cluster;
+	toff = (swp_offset(entry) >> our_page_cluster) << our_page_cluster;
 	if (!toff)		/* first page is swap header */
 		toff++, i--;
 	*offset = toff;
diff --git a/net/802/tr.c b/net/802/tr.c
index d7d8f40..829deb4 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -164,7 +164,7 @@
 	 */
 	 
 	if(trllc->ethertype != htons(ETH_P_IP)) {
-		printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(trllc->ethertype));
+		printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(trllc->ethertype));
 		return 0;
 	}
 
@@ -186,7 +186,7 @@
  *	it via SNAP.
  */
  
-unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev) 
+__be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 
 	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
@@ -229,15 +229,15 @@
 	 */
 
 	if (trllc->dsap == EXTENDED_SAP &&
-	    (trllc->ethertype == ntohs(ETH_P_IP) ||
-	     trllc->ethertype == ntohs(ETH_P_IPV6) ||
-	     trllc->ethertype == ntohs(ETH_P_ARP)))
+	    (trllc->ethertype == htons(ETH_P_IP) ||
+	     trllc->ethertype == htons(ETH_P_IPV6) ||
+	     trllc->ethertype == htons(ETH_P_ARP)))
 	{
 		skb_pull(skb, sizeof(struct trllc));
 		return trllc->ethertype;
 	}
 
-	return ntohs(ETH_P_TR_802_2);
+	return htons(ETH_P_TR_802_2);
 }
 
 /*
diff --git a/net/Kconfig b/net/Kconfig
index 6528a935..a81aca4 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -231,7 +231,7 @@
 	TCP congestion avoidance modules. If you don't understand
 	what was just said, you don't need it: say N.
 
-	Documentation on how to use the packet generator can be found
+	Documentation on how to use TCP connection probing can be found
 	at http://linux-net.osdl.org/index.php/TcpProbe
 
 	To compile this code as a module, choose M here: the
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 96dc6bb..708e2e0 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1002,7 +1002,7 @@
 	return sum;
 }
 
-static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
+static __be16 atalk_checksum(const struct sk_buff *skb, int len)
 {
 	unsigned long sum;
 
@@ -1010,7 +1010,7 @@
 	sum = atalk_sum_skb(skb, 4, len-4, 0);
 
 	/* Use 0xFFFF for 0. 0 itself means none */
-	return sum ? htons((unsigned short)sum) : 0xFFFF;
+	return sum ? htons((unsigned short)sum) : htons(0xFFFF);
 }
 
 static struct proto ddp_proto = {
@@ -1289,7 +1289,7 @@
 #endif
 
 static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
-			       struct ddpehdr *ddp, struct ddpebits *ddphv,
+			       struct ddpehdr *ddp, __u16 len_hops,
 			       int origlen)
 {
 	struct atalk_route *rt;
@@ -1317,10 +1317,12 @@
 
 	/* Route the packet */
 	rt = atrtr_find(&ta);
-	if (!rt || ddphv->deh_hops == DDP_MAXHOPS)
+	/* increment hops count */
+	len_hops += 1 << 10;
+	if (!rt || !(len_hops & (15 << 10)))
 		goto free_it;
+
 	/* FIXME: use skb->cb to be able to use shared skbs */
-	ddphv->deh_hops++;
 
 	/*
 	 * Route goes through another gateway, so set the target to the
@@ -1335,11 +1337,10 @@
         /* Fix up skb->len field */
         skb_trim(skb, min_t(unsigned int, origlen,
 			    (rt->dev->hard_header_len +
-			     ddp_dl->header_length + ddphv->deh_len)));
+			     ddp_dl->header_length + (len_hops & 1023))));
 
-	/* Mend the byte order */
 	/* FIXME: use skb->cb to be able to use shared skbs */
-	*((__u16 *)ddp) = ntohs(*((__u16 *)ddphv));
+	ddp->deh_len_hops = htons(len_hops);
 
 	/*
 	 * Send the buffer onwards
@@ -1394,7 +1395,7 @@
 	struct atalk_iface *atif;
 	struct sockaddr_at tosat;
         int origlen;
-        struct ddpebits ddphv;
+	__u16 len_hops;
 
 	/* Don't mangle buffer if shared */
 	if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 
@@ -1406,16 +1407,11 @@
 
 	ddp = ddp_hdr(skb);
 
-	/*
-	 *	Fix up the length field	[Ok this is horrible but otherwise
-	 *	I end up with unions of bit fields and messy bit field order
-	 *	compiler/endian dependencies..]
-	 */
-	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
+	len_hops = ntohs(ddp->deh_len_hops);
 
 	/* Trim buffer in case of stray trailing data */
 	origlen = skb->len;
-	skb_trim(skb, min_t(unsigned int, skb->len, ddphv.deh_len));
+	skb_trim(skb, min_t(unsigned int, skb->len, len_hops & 1023));
 
 	/*
 	 * Size check to see if ddp->deh_len was crap
@@ -1430,7 +1426,7 @@
 	 * valid for net byte orders all over the networking code...
 	 */
 	if (ddp->deh_sum &&
-	    atalk_checksum(skb, ddphv.deh_len) != ddp->deh_sum)
+	    atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
 		/* Not a valid AppleTalk frame - dustbin time */
 		goto freeit;
 
@@ -1444,7 +1440,7 @@
 		/* Not ours, so we route the packet via the correct
 		 * AppleTalk iface
 		 */
-		atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
+		atalk_route_packet(skb, dev, ddp, len_hops, origlen);
 		goto out;
 	}
 
@@ -1489,7 +1485,7 @@
 		/* Find our address */
 		struct atalk_addr *ap = atalk_find_dev_addr(dev);
 
-		if (!ap || skb->len < sizeof(struct ddpshdr))
+		if (!ap || skb->len < sizeof(__be16) || skb->len > 1023)
 			goto freeit;
 
 		/* Don't mangle buffer if shared */
@@ -1519,11 +1515,8 @@
 		/*
 		 * Not sure about this bit...
 		 */
-		ddp->deh_len   = skb->len;
-		ddp->deh_hops  = DDP_MAXHOPS;	/* Non routable, so force a drop
-						   if we slip up later */
-		/* Mend the byte order */
-		*((__u16 *)ddp) = htons(*((__u16 *)ddp));
+		/* Non routable, so force a drop if we slip up later */
+		ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10));
 	}
 	skb->h.raw = skb->data;
 
@@ -1622,16 +1615,7 @@
 	SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
 
 	ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));
-	ddp->deh_pad  = 0;
-	ddp->deh_hops = 0;
-	ddp->deh_len  = len + sizeof(*ddp);
-	/*
-	 * Fix up the length field [Ok this is horrible but otherwise
-	 * I end up with unions of bit fields and messy bit field order
-	 * compiler/endian dependencies..
-	 */
-	*((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
-
+	ddp->deh_len_hops  = htons(len + sizeof(*ddp));
 	ddp->deh_dnet  = usat->sat_addr.s_net;
 	ddp->deh_snet  = at->src_net;
 	ddp->deh_dnode = usat->sat_addr.s_node;
@@ -1712,8 +1696,8 @@
 	struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
 	struct ddpehdr *ddp;
 	int copied = 0;
+	int offset = 0;
 	int err = 0;
-        struct ddpebits ddphv;
 	struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 						flags & MSG_DONTWAIT, &err);
 	if (!skb)
@@ -1721,26 +1705,19 @@
 
 	/* FIXME: use skb->cb to be able to use shared skbs */
 	ddp = ddp_hdr(skb);
-	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
+	copied = ntohs(ddp->deh_len_hops) & 1023;
 
-	if (sk->sk_type == SOCK_RAW) {
-		copied = ddphv.deh_len;
-		if (copied > size) {
-			copied = size;
-			msg->msg_flags |= MSG_TRUNC;
-		}
-
-		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-	} else {
-		copied = ddphv.deh_len - sizeof(*ddp);
-		if (copied > size) {
-			copied = size;
-			msg->msg_flags |= MSG_TRUNC;
-		}
-		err = skb_copy_datagram_iovec(skb, sizeof(*ddp),
-					      msg->msg_iov, copied);
+	if (sk->sk_type != SOCK_RAW) {
+		offset = sizeof(*ddp);
+		copied -= offset;
 	}
 
+	if (copied > size) {
+		copied = size;
+		msg->msg_flags |= MSG_TRUNC;
+	}
+	err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
+
 	if (!err) {
 		if (sat) {
 			sat->sat_family      = AF_APPLETALK;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index b87c2a8..0d2b994 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -560,7 +560,6 @@
 	struct atmmpc_ioc ioc_data;
 	in_cache_entry *in_entry;
 	uint32_t  ipaddr;
-	unsigned char *ip;
 
 	bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc));
 	if (bytes_left != 0) {
@@ -583,9 +582,8 @@
 			if (in_entry != NULL) mpc->in_ops->put(in_entry);
 			return -EINVAL;
 		}
-		ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip;
 		printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
-		       mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+		       mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
 		in_entry->shortcut = vcc;
 		mpc->in_ops->put(in_entry);
 	} else {
@@ -616,10 +614,8 @@
 	dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
 	in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
 	if (in_entry) {
-		unsigned char *ip __attribute__ ((unused)) =
-		    (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
 		dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
-		       mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+		       mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
 		in_entry->shortcut = NULL;
 		mpc->in_ops->put(in_entry);
 	}
@@ -1154,18 +1150,17 @@
 {
 	uint32_t dst_ip = msg->content.in_info.in_dst_ip;
 	uint32_t mask = msg->ip_mask;
-	unsigned char *ip = (unsigned char *)&dst_ip;
 	in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
 
 	if(entry == NULL){
 		printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
-		printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+		printk("ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
 		return;
 	}
 
 	do {
 		dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
-			mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+			mpc->dev->name, NIPQUAD(dst_ip));
 		write_lock_bh(&mpc->ingress_lock);
 		mpc->in_ops->remove_entry(entry, mpc);
 		write_unlock_bh(&mpc->ingress_lock);
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 781ed1b..fbf13cd 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -87,7 +87,6 @@
 static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
 					  struct mpoa_client *client)
 {
-	unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
 	in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
 
 	if (entry == NULL) {
@@ -95,7 +94,7 @@
 		return NULL;
 	}
 
-	dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+	dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
 	memset(entry,0,sizeof(in_cache_entry));
 
 	atomic_set(&entry->use, 1);
@@ -152,10 +151,7 @@
 
 	if( entry->count > mpc->parameters.mpc_p1 &&
 	    entry->entry_state == INGRESS_INVALID){
-		unsigned char *ip __attribute__ ((unused)) =
-		    (unsigned char *)&entry->ctrl_info.in_dst_ip;
-
-		dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+		dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, NIPQUAD(entry->ctrl_info.in_dst_ip));
 		entry->entry_state = INGRESS_RESOLVING;
 		msg.type =  SND_MPOA_RES_RQST;
 		memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
@@ -187,11 +183,9 @@
 {
 	struct atm_vcc *vcc;
 	struct k_message msg;
-	unsigned char *ip;
 
 	vcc = entry->shortcut;
-	ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
-	dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
+	dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",NIPQUAD(entry->ctrl_info.in_dst_ip));
 
 	if (entry->prev != NULL)
 		entry->prev->next = entry->next;
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 788ea7a..305a099 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -276,7 +276,7 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 
 		if (!timeo) {
-			err = -EAGAIN;
+			err = -EINPROGRESS;
 			break;
 		}
 
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index e620061..2312d05 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -51,6 +51,7 @@
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "bnep.h"
@@ -515,6 +516,26 @@
 	return 0;
 }
 
+static struct device *bnep_get_device(struct bnep_session *session)
+{
+	bdaddr_t *src = &bt_sk(session->sock->sk)->src;
+	bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
+	struct hci_dev *hdev;
+	struct hci_conn *conn;
+
+	hdev = hci_get_route(dst, src);
+	if (!hdev)
+		return NULL;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+	if (!conn)
+		return NULL;
+
+	hci_dev_put(hdev);
+
+	return &conn->dev;
+}
+
 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
 {
 	struct net_device *dev;
@@ -534,7 +555,6 @@
 	if (!dev)
 		return -ENOMEM;
 
-
 	down_write(&bnep_session_sem);
 
 	ss = __bnep_get_session(dst);
@@ -551,7 +571,7 @@
 	memcpy(s->eh.h_source, &dst, ETH_ALEN);
 	memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
 
-	s->dev = dev;
+	s->dev   = dev;
 	s->sock  = sock;
 	s->role  = req->role;
 	s->state = BT_CONNECTED;
@@ -568,6 +588,8 @@
 	bnep_set_default_proto_filter(s);
 #endif
 
+	SET_NETDEV_DEV(dev, bnep_get_device(s));
+
 	err = register_netdev(dev);
 	if (err) {
 		goto failed;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 420ed4d..90e3a28 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -84,6 +84,20 @@
 	hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
 }
 
+static void hci_acl_connect_cancel(struct hci_conn *conn)
+{
+	struct hci_cp_create_conn_cancel cp;
+
+	BT_DBG("%p", conn);
+
+	if (conn->hdev->hci_ver < 2)
+		return;
+
+	bacpy(&cp.bdaddr, &conn->dst);
+	hci_send_cmd(conn->hdev, OGF_LINK_CTL,
+				OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp);
+}
+
 void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
 {
 	struct hci_cp_disconnect cp;
@@ -94,7 +108,8 @@
 
 	cp.handle = __cpu_to_le16(conn->handle);
 	cp.reason = reason;
-	hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT, sizeof(cp), &cp);
+	hci_send_cmd(conn->hdev, OGF_LINK_CTL,
+				OCF_DISCONNECT, sizeof(cp), &cp);
 }
 
 void hci_add_sco(struct hci_conn *conn, __u16 handle)
@@ -124,12 +139,20 @@
 		return;
 
 	hci_dev_lock(hdev);
- 	if (conn->state == BT_CONNECTED)
+
+	switch (conn->state) {
+	case BT_CONNECT:
+		hci_acl_connect_cancel(conn);
+		break;
+ 	case BT_CONNECTED:
 		hci_acl_disconn(conn, 0x13);
-	else
+		break;
+	default:
 		conn->state = BT_CLOSED;
+		break;
+	}
+
 	hci_dev_unlock(hdev);
-	return;
 }
 
 static void hci_conn_idle(unsigned long arg)
@@ -179,6 +202,8 @@
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
 
+	hci_conn_add_sysfs(conn);
+
 	tasklet_enable(&hdev->tx_task);
 
 	return conn;
@@ -211,6 +236,8 @@
 
 	tasklet_disable(&hdev->tx_task);
 
+	hci_conn_del_sysfs(conn);
+
 	hci_conn_hash_del(hdev, conn);
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
@@ -221,7 +248,9 @@
 
 	hci_dev_put(hdev);
 
-	kfree(conn);
+	/* will free via device release */
+	put_device(&conn->dev);
+
 	return 0;
 }
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5ed4742..338ae97 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -206,6 +206,9 @@
 	/* Read Local Supported Features */
 	hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL);
 
+	/* Read Local Version */
+	hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL);
+
 	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
 	hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL);
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3896dab..d43d0c8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -62,6 +62,7 @@
 
 	switch (ocf) {
 	case OCF_INQUIRY_CANCEL:
+	case OCF_EXIT_PERIODIC_INQ:
 		status = *((__u8 *) skb->data);
 
 		if (status) {
@@ -297,6 +298,7 @@
 /* Command Complete OGF INFO_PARAM  */
 static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
 {
+	struct hci_rp_read_loc_version *lv;
 	struct hci_rp_read_local_features *lf;
 	struct hci_rp_read_buffer_size *bs;
 	struct hci_rp_read_bd_addr *ba;
@@ -304,6 +306,23 @@
 	BT_DBG("%s ocf 0x%x", hdev->name, ocf);
 
 	switch (ocf) {
+	case OCF_READ_LOCAL_VERSION:
+		lv = (struct hci_rp_read_loc_version *) skb->data;
+
+		if (lv->status) {
+			BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status);
+			break;
+		}
+
+		hdev->hci_ver = lv->hci_ver;
+		hdev->hci_rev = btohs(lv->hci_rev);
+		hdev->manufacturer = btohs(lv->manufacturer);
+
+		BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name,
+				hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
+
+		break;
+
 	case OCF_READ_LOCAL_FEATURES:
 		lf = (struct hci_rp_read_local_features *) skb->data;
 
@@ -328,7 +347,8 @@
 		if (hdev->features[1] & LMP_HV3)
 			hdev->pkt_type |= (HCI_HV3);
 
-		BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, lf->features[0], lf->features[1], lf->features[2]);
+		BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
+				lf->features[0], lf->features[1], lf->features[2]);
 
 		break;
 
@@ -757,6 +777,10 @@
 
 			hci_send_cmd(hdev, OGF_LINK_CTL,
 				OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
+		} else {
+			/* Update disconnect timer */
+			hci_conn_hold(conn);
+			hci_conn_put(conn);
 		}
 	} else
 		conn->state = BT_CLOSED;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 3987d16..989b22d 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -13,16 +13,32 @@
 #define BT_DBG(D...)
 #endif
 
-static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+static inline char *typetostr(int type)
 {
-	struct hci_dev *hdev = dev_get_drvdata(dev);
-	return sprintf(buf, "%s\n", hdev->name);
+	switch (type) {
+	case HCI_VIRTUAL:
+		return "VIRTUAL";
+	case HCI_USB:
+		return "USB";
+	case HCI_PCCARD:
+		return "PCCARD";
+	case HCI_UART:
+		return "UART";
+	case HCI_RS232:
+		return "RS232";
+	case HCI_PCI:
+		return "PCI";
+	case HCI_SDIO:
+		return "SDIO";
+	default:
+		return "UNKNOWN";
+	}
 }
 
 static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
-	return sprintf(buf, "%d\n", hdev->type);
+	return sprintf(buf, "%s\n", typetostr(hdev->type));
 }
 
 static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf)
@@ -33,10 +49,22 @@
 	return sprintf(buf, "%s\n", batostr(&bdaddr));
 }
 
-static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
-	return sprintf(buf, "0x%lx\n", hdev->flags);
+	return sprintf(buf, "%d\n", hdev->manufacturer);
+}
+
+static ssize_t show_hci_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", hdev->hci_ver);
+}
+
+static ssize_t show_hci_revision(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", hdev->hci_rev);
 }
 
 static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf)
@@ -141,10 +169,11 @@
 	return count;
 }
 
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
-static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
+static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
+static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
+static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
 static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
 
 static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
@@ -155,10 +184,11 @@
 				show_sniff_min_interval, store_sniff_min_interval);
 
 static struct device_attribute *bt_attrs[] = {
-	&dev_attr_name,
 	&dev_attr_type,
 	&dev_attr_address,
-	&dev_attr_flags,
+	&dev_attr_manufacturer,
+	&dev_attr_hci_version,
+	&dev_attr_hci_revision,
 	&dev_attr_inquiry_cache,
 	&dev_attr_idle_timeout,
 	&dev_attr_sniff_max_interval,
@@ -166,6 +196,32 @@
 	NULL
 };
 
+static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_conn *conn = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO");
+}
+
+static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_conn *conn = dev_get_drvdata(dev);
+	bdaddr_t bdaddr;
+	baswap(&bdaddr, &conn->dst);
+	return sprintf(buf, "%s\n", batostr(&bdaddr));
+}
+
+#define CONN_ATTR(_name,_mode,_show,_store) \
+struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store)
+
+static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL);
+static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL);
+
+static struct device_attribute *conn_attrs[] = {
+	&conn_attr_type,
+	&conn_attr_address,
+	NULL
+};
+
 struct class *bt_class = NULL;
 EXPORT_SYMBOL_GPL(bt_class);
 
@@ -177,8 +233,57 @@
 
 static void bt_release(struct device *dev)
 {
-	struct hci_dev *hdev = dev_get_drvdata(dev);
-	kfree(hdev);
+	void *data = dev_get_drvdata(dev);
+	kfree(data);
+}
+
+static void add_conn(void *data)
+{
+	struct hci_conn *conn = data;
+	int i;
+
+	device_register(&conn->dev);
+
+	for (i = 0; conn_attrs[i]; i++)
+		device_create_file(&conn->dev, conn_attrs[i]);
+}
+
+void hci_conn_add_sysfs(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	bdaddr_t *ba = &conn->dst;
+
+	BT_DBG("conn %p", conn);
+
+	conn->dev.parent  = &hdev->dev;
+	conn->dev.release = bt_release;
+
+	snprintf(conn->dev.bus_id, BUS_ID_SIZE,
+			"%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+			conn->type == ACL_LINK ? "acl" : "sco",
+			ba->b[5], ba->b[4], ba->b[3],
+			ba->b[2], ba->b[1], ba->b[0]);
+
+	dev_set_drvdata(&conn->dev, conn);
+
+	INIT_WORK(&conn->work, add_conn, (void *) conn);
+
+	schedule_work(&conn->work);
+}
+
+static void del_conn(void *data)
+{
+	struct hci_conn *conn = data;
+	device_del(&conn->dev);
+}
+
+void hci_conn_del_sysfs(struct hci_conn *conn)
+{
+	BT_DBG("conn %p", conn);
+
+	INIT_WORK(&conn->work, del_conn, (void *) conn);
+
+	schedule_work(&conn->work);
 }
 
 int hci_register_sysfs(struct hci_dev *hdev)
@@ -214,11 +319,9 @@
 
 void hci_unregister_sysfs(struct hci_dev *hdev)
 {
-	struct device *dev = &hdev->dev;
-
 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
-	device_del(dev);
+	device_del(&hdev->dev);
 }
 
 int __init bt_sysfs_init(void)
@@ -245,7 +348,7 @@
 	return 0;
 }
 
-void __exit bt_sysfs_cleanup(void)
+void bt_sysfs_cleanup(void)
 {
 	class_destroy(bt_class);
 
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index c6e3a2c..03b5dad 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -40,6 +40,7 @@
 #include <linux/input.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "hidp.h"
@@ -528,6 +529,26 @@
 	return 0;
 }
 
+static struct device *hidp_get_device(struct hidp_session *session)
+{
+	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
+	bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
+	struct hci_dev *hdev;
+	struct hci_conn *conn;
+
+	hdev = hci_get_route(dst, src);
+	if (!hdev)
+		return NULL;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+	if (!conn)
+		return NULL;
+
+	hci_dev_put(hdev);
+
+	return &conn->dev;
+}
+
 static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
 {
 	struct input_dev *input = session->input;
@@ -566,6 +587,8 @@
 		input->relbit[0] |= BIT(REL_WHEEL);
 	}
 
+	input->cdev.dev = hidp_get_device(session);
+
 	input->event = hidp_input_event;
 
 	input_register_device(input);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 332dd8f..468df3b 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -644,7 +644,7 @@
 	addr.l2_family = AF_BLUETOOTH;
 	addr.l2_psm    = htobs(RFCOMM_PSM);
 	*err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
-	if (*err == 0 || *err == -EAGAIN)
+	if (*err == 0 || *err == -EINPROGRESS)
 		return s;
 
 	rfcomm_session_del(s);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index bd8d671..26f3227 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -38,6 +38,7 @@
 #include <linux/skbuff.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/rfcomm.h>
 
 #ifndef CONFIG_BT_RFCOMM_DEBUG
@@ -161,6 +162,24 @@
 	return dev;
 }
 
+static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
+{
+	struct hci_dev *hdev;
+	struct hci_conn *conn;
+
+	hdev = hci_get_route(&dev->dst, &dev->src);
+	if (!hdev)
+		return NULL;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
+	if (!conn)
+		return NULL;
+
+	hci_dev_put(hdev);
+
+	return &conn->dev;
+}
+
 static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 {
 	struct rfcomm_dev *dev;
@@ -244,7 +263,7 @@
 		return err;
 	}
 
-	tty_register_device(rfcomm_tty_driver, dev->id, NULL);
+	tty_register_device(rfcomm_tty_driver, dev->id, rfcomm_get_device(dev));
 
 	return dev->id;
 }
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index d19fc4b..0aa7b99 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -20,7 +20,7 @@
    const void *data, unsigned int datalen)
 {
 	struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data;
-	u32 _sip, *siptr, _dip, *diptr;
+	__be32 _sip, *siptr, _dip, *diptr;
 	struct arphdr _ah, *ap;
 	unsigned char _sha[ETH_ALEN], *shp;
 	struct sk_buff *skb = *pskb;
diff --git a/net/core/dev.c b/net/core/dev.c
index 14de297..4d891be 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1480,14 +1480,16 @@
 	if (q->enqueue) {
 		/* Grab device queue */
 		spin_lock(&dev->queue_lock);
+		q = dev->qdisc;
+		if (q->enqueue) {
+			rc = q->enqueue(skb, q);
+			qdisc_run(dev);
+			spin_unlock(&dev->queue_lock);
 
-		rc = q->enqueue(skb, q);
-
-		qdisc_run(dev);
-
+			rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
+			goto out;
+		}
 		spin_unlock(&dev->queue_lock);
-		rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
-		goto out;
 	}
 
 	/* The device has no queue. Common case for software devices:
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index e0ca04f..87dc556 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -806,13 +806,6 @@
 	int rc;
 	unsigned long old_features;
 
-	/*
-	 * XXX: This can be pushed down into the ethtool_* handlers that
-	 * need it.  Keep existing behaviour for the moment.
-	 */
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
 	if (!dev || !netif_device_present(dev))
 		return -ENODEV;
 
@@ -822,6 +815,27 @@
 	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
 		return -EFAULT;
 
+	/* Allow some commands to be done by anyone */
+	switch(ethcmd) {
+	case ETHTOOL_GDRVINFO:
+	case ETHTOOL_GMSGLVL:
+	case ETHTOOL_GCOALESCE:
+	case ETHTOOL_GRINGPARAM:
+	case ETHTOOL_GPAUSEPARAM:
+	case ETHTOOL_GRXCSUM:
+	case ETHTOOL_GTXCSUM:
+	case ETHTOOL_GSG:
+	case ETHTOOL_GSTRINGS:
+	case ETHTOOL_GTSO:
+	case ETHTOOL_GPERMADDR:
+	case ETHTOOL_GUFO:
+	case ETHTOOL_GGSO:
+		break;
+	default:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+	}
+
 	if(dev->ethtool_ops->begin)
 		if ((rc = dev->ethtool_ops->begin(dev)) < 0)
 			return rc;
@@ -947,6 +961,10 @@
 	return rc;
 
  ioctl:
+	/* Keep existing behaviour for the moment.	 */
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
 	if (dev->do_ioctl)
 		return dev->do_ioctl(dev, ifr, SIOCETHTOOL);
 	return -EOPNOTSUPP;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b6c69e1..8ce8c47 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1079,7 +1079,7 @@
 }
 
 static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
-			  u16 protocol)
+			  __be16 protocol)
 {
 	struct hh_cache	*hh;
 	struct net_device *dev = dst->dev;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 1347276..f47f319 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -344,8 +344,6 @@
 		if(dev->wireless_handlers &&
 		   dev->wireless_handlers->get_wireless_stats)
 			iw = dev->wireless_handlers->get_wireless_stats(dev);
-		else if (dev->get_wireless_stats)
-			iw = dev->get_wireless_stats(dev);
 		if (iw != NULL)
 			ret = (*format)(iw, buf);
 	}
@@ -465,8 +463,7 @@
 		*groups++ = &netstat_group;
 
 #ifdef WIRELESS_EXT
-	if (net->get_wireless_stats
-	    || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
+	if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
 		*groups++ = &wireless_group;
 #endif
 
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 72145d4..dd023fd 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -109,6 +109,8 @@
  *
  * MPLS support by Steven Whitehouse <steve@chygwyn.com>
  *
+ * 802.1Q/Q-in-Q support by Francesco Fondelli (FF) <francesco.fondelli@gmail.com>
+ *
  */
 #include <linux/sys.h>
 #include <linux/types.h>
@@ -137,6 +139,7 @@
 #include <linux/inetdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_arp.h>
+#include <linux/if_vlan.h>
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
@@ -157,7 +160,7 @@
 #include <asm/div64.h>		/* do_div */
 #include <asm/timex.h>
 
-#define VERSION  "pktgen v2.67: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.68: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a)
@@ -178,6 +181,8 @@
 #define F_TXSIZE_RND  (1<<6)	/* Transmit size is random */
 #define F_IPV6        (1<<7)	/* Interface in IPV6 Mode */
 #define F_MPLS_RND    (1<<8)	/* Random MPLS labels */
+#define F_VID_RND     (1<<9)	/* Random VLAN ID */
+#define F_SVID_RND    (1<<10)	/* Random SVLAN ID */
 
 /* Thread control flag bits */
 #define T_TERMINATE   (1<<0)
@@ -198,6 +203,9 @@
 
 #define MAX_CFLOWS  65536
 
+#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
+#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
+
 struct flow_state {
 	__u32 cur_daddr;
 	int count;
@@ -284,10 +292,23 @@
 	__u16 udp_dst_min;	/* inclusive, dest UDP port */
 	__u16 udp_dst_max;	/* exclusive, dest UDP port */
 
+	/* DSCP + ECN */
+	__u8 tos;            /* six most significant bits of (former) IPv4 TOS are for dscp codepoint */
+	__u8 traffic_class;  /* ditto for the (former) Traffic Class in IPv6 (see RFC 3260, sec. 4) */
+
 	/* MPLS */
 	unsigned nr_labels;	/* Depth of stack, 0 = no MPLS */
 	__be32 labels[MAX_MPLS_LABELS];
 
+	/* VLAN/SVLAN (802.1Q/Q-in-Q) */
+	__u8  vlan_p;
+	__u8  vlan_cfi;
+	__u16 vlan_id;  /* 0xffff means no vlan tag */
+
+	__u8  svlan_p;
+	__u8  svlan_cfi;
+	__u16 svlan_id; /* 0xffff means no svlan tag */
+
 	__u32 src_mac_count;	/* How many MACs to iterate through */
 	__u32 dst_mac_count;	/* How many MACs to iterate through */
 
@@ -644,6 +665,24 @@
 				   i == pkt_dev->nr_labels-1 ? "\n" : ", ");
 	}
 
+	if (pkt_dev->vlan_id != 0xffff) {
+		seq_printf(seq, "     vlan_id: %u  vlan_p: %u  vlan_cfi: %u\n",
+			   pkt_dev->vlan_id, pkt_dev->vlan_p, pkt_dev->vlan_cfi);
+	}
+
+	if (pkt_dev->svlan_id != 0xffff) {
+		seq_printf(seq, "     svlan_id: %u  vlan_p: %u  vlan_cfi: %u\n",
+			   pkt_dev->svlan_id, pkt_dev->svlan_p, pkt_dev->svlan_cfi);
+	}
+
+	if (pkt_dev->tos) {
+		seq_printf(seq, "     tos: 0x%02x\n", pkt_dev->tos);
+	}
+
+	if (pkt_dev->traffic_class) {
+		seq_printf(seq, "     traffic_class: 0x%02x\n", pkt_dev->traffic_class);
+	}
+
 	seq_printf(seq, "     Flags: ");
 
 	if (pkt_dev->flags & F_IPV6)
@@ -673,6 +712,12 @@
 	if (pkt_dev->flags & F_MACDST_RND)
 		seq_printf(seq, "MACDST_RND  ");
 
+	if (pkt_dev->flags & F_VID_RND)
+		seq_printf(seq, "VID_RND  ");
+
+	if (pkt_dev->flags & F_SVID_RND)
+		seq_printf(seq, "SVID_RND  ");
+
 	seq_puts(seq, "\n");
 
 	sa = pkt_dev->started_at;
@@ -715,12 +760,12 @@
 }
 
 
-static int hex32_arg(const char __user *user_buffer, __u32 *num)
+static int hex32_arg(const char __user *user_buffer, unsigned long maxlen, __u32 *num)
 {
 	int i = 0;
 	*num = 0;
 
-	for(; i < 8; i++) {
+	for(; i < maxlen; i++) {
 		char c;
 		*num <<= 4;
 		if (get_user(c, &user_buffer[i]))
@@ -815,7 +860,7 @@
 	pkt_dev->nr_labels = 0;
 	do {
 		__u32 tmp;
-		len = hex32_arg(&buffer[i], &tmp);
+		len = hex32_arg(&buffer[i], 8, &tmp);
 		if (len <= 0)
 			return len;
 		pkt_dev->labels[n] = htonl(tmp);
@@ -1140,11 +1185,27 @@
 		else if (strcmp(f, "!MPLS_RND") == 0)
 			pkt_dev->flags &= ~F_MPLS_RND;
 
+		else if (strcmp(f, "VID_RND") == 0)
+			pkt_dev->flags |= F_VID_RND;
+
+		else if (strcmp(f, "!VID_RND") == 0)
+			pkt_dev->flags &= ~F_VID_RND;
+
+		else if (strcmp(f, "SVID_RND") == 0)
+			pkt_dev->flags |= F_SVID_RND;
+
+		else if (strcmp(f, "!SVID_RND") == 0)
+			pkt_dev->flags &= ~F_SVID_RND;
+
+		else if (strcmp(f, "!IPV6") == 0)
+			pkt_dev->flags &= ~F_IPV6;
+
 		else {
 			sprintf(pg_result,
 				"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
 				f,
-				"IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
+				"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, "
+				"MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n");
 			return count;
 		}
 		sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
@@ -1445,6 +1506,160 @@
 			offset += sprintf(pg_result + offset,
 					  "%08x%s", ntohl(pkt_dev->labels[n]),
 					  n == pkt_dev->nr_labels-1 ? "" : ",");
+
+		if (pkt_dev->nr_labels && pkt_dev->vlan_id != 0xffff) {
+			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
+			pkt_dev->svlan_id = 0xffff;
+
+			if (debug)
+				printk("pktgen: VLAN/SVLAN auto turned off\n");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "vlan_id")) {
+		len = num_arg(&user_buffer[i], 4, &value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if (value <= 4095) {
+			pkt_dev->vlan_id = value;  /* turn on VLAN */
+
+			if (debug)
+				printk("pktgen: VLAN turned on\n");
+
+			if (debug && pkt_dev->nr_labels)
+				printk("pktgen: MPLS auto turned off\n");
+
+			pkt_dev->nr_labels = 0;    /* turn off MPLS */
+			sprintf(pg_result, "OK: vlan_id=%u", pkt_dev->vlan_id);
+		} else {
+			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
+			pkt_dev->svlan_id = 0xffff;
+
+			if (debug)
+				printk("pktgen: VLAN/SVLAN turned off\n");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "vlan_p")) {
+		len = num_arg(&user_buffer[i], 1, &value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if ((value <= 7) && (pkt_dev->vlan_id != 0xffff)) {
+			pkt_dev->vlan_p = value;
+			sprintf(pg_result, "OK: vlan_p=%u", pkt_dev->vlan_p);
+		} else {
+			sprintf(pg_result, "ERROR: vlan_p must be 0-7");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "vlan_cfi")) {
+		len = num_arg(&user_buffer[i], 1, &value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if ((value <= 1) && (pkt_dev->vlan_id != 0xffff)) {
+			pkt_dev->vlan_cfi = value;
+			sprintf(pg_result, "OK: vlan_cfi=%u", pkt_dev->vlan_cfi);
+		} else {
+			sprintf(pg_result, "ERROR: vlan_cfi must be 0-1");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "svlan_id")) {
+		len = num_arg(&user_buffer[i], 4, &value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if ((value <= 4095) && ((pkt_dev->vlan_id != 0xffff))) {
+			pkt_dev->svlan_id = value;  /* turn on SVLAN */
+
+			if (debug)
+				printk("pktgen: SVLAN turned on\n");
+
+			if (debug && pkt_dev->nr_labels)
+				printk("pktgen: MPLS auto turned off\n");
+
+			pkt_dev->nr_labels = 0;    /* turn off MPLS */
+			sprintf(pg_result, "OK: svlan_id=%u", pkt_dev->svlan_id);
+		} else {
+			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
+			pkt_dev->svlan_id = 0xffff;
+
+			if (debug)
+				printk("pktgen: VLAN/SVLAN turned off\n");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "svlan_p")) {
+		len = num_arg(&user_buffer[i], 1, &value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if ((value <= 7) && (pkt_dev->svlan_id != 0xffff)) {
+			pkt_dev->svlan_p = value;
+			sprintf(pg_result, "OK: svlan_p=%u", pkt_dev->svlan_p);
+		} else {
+			sprintf(pg_result, "ERROR: svlan_p must be 0-7");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "svlan_cfi")) {
+		len = num_arg(&user_buffer[i], 1, &value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if ((value <= 1) && (pkt_dev->svlan_id != 0xffff)) {
+			pkt_dev->svlan_cfi = value;
+			sprintf(pg_result, "OK: svlan_cfi=%u", pkt_dev->svlan_cfi);
+		} else {
+			sprintf(pg_result, "ERROR: svlan_cfi must be 0-1");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "tos")) {
+		__u32 tmp_value = 0;
+		len = hex32_arg(&user_buffer[i], 2, &tmp_value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if (len == 2) {
+			pkt_dev->tos = tmp_value;
+			sprintf(pg_result, "OK: tos=0x%02x", pkt_dev->tos);
+		} else {
+			sprintf(pg_result, "ERROR: tos must be 00-ff");
+		}
+		return count;
+	}
+
+	if (!strcmp(name, "traffic_class")) {
+		__u32 tmp_value = 0;
+		len = hex32_arg(&user_buffer[i], 2, &tmp_value);
+		if (len < 0) {
+			return len;
+		}
+		i += len;
+		if (len == 2) {
+			pkt_dev->traffic_class = tmp_value;
+			sprintf(pg_result, "OK: traffic_class=0x%02x", pkt_dev->traffic_class);
+		} else {
+			sprintf(pg_result, "ERROR: traffic_class must be 00-ff");
+		}
 		return count;
 	}
 
@@ -1949,6 +2164,14 @@
 						      htonl(0x000fffff));
 	}
 
+	if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) {
+		pkt_dev->vlan_id = pktgen_random() % 4096;
+	}
+
+	if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) {
+		pkt_dev->svlan_id = pktgen_random() % 4096;
+	}
+
 	if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
 		if (pkt_dev->flags & F_UDPSRC_RND)
 			pkt_dev->cur_udp_src =
@@ -2092,10 +2315,18 @@
 	struct pktgen_hdr *pgh = NULL;
 	__be16 protocol = __constant_htons(ETH_P_IP);
 	__be32 *mpls;
+	__be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
+	__be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
+	__be16 *svlan_tci = NULL;                /* Encapsulates priority and SVLAN ID */
+	__be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
+
 
 	if (pkt_dev->nr_labels)
 		protocol = __constant_htons(ETH_P_MPLS_UC);
 
+	if (pkt_dev->vlan_id != 0xffff)
+		protocol = __constant_htons(ETH_P_8021Q);
+
 	/* Update any of the values, used when we're incrementing various
 	 * fields.
 	 */
@@ -2103,7 +2334,9 @@
 
 	datalen = (odev->hard_header_len + 16) & ~0xf;
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
-			pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
+			pkt_dev->nr_labels*sizeof(u32) +
+			VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
+			GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -2116,6 +2349,24 @@
 	mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
 	if (pkt_dev->nr_labels)
 		mpls_push(mpls, pkt_dev);
+
+	if (pkt_dev->vlan_id != 0xffff) {
+		if(pkt_dev->svlan_id != 0xffff) {
+			svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+			*svlan_tci = htons(pkt_dev->svlan_id);
+			*svlan_tci |= pkt_dev->svlan_p << 5;
+			*svlan_tci |= pkt_dev->svlan_cfi << 4;
+			svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+			*svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
+		}
+		vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+		*vlan_tci = htons(pkt_dev->vlan_id);
+		*vlan_tci |= pkt_dev->vlan_p << 5;
+		*vlan_tci |= pkt_dev->vlan_cfi << 4;
+		vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+		*vlan_encapsulated_proto = __constant_htons(ETH_P_IP);
+	}
+
 	iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
 	udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
 
@@ -2124,7 +2375,7 @@
 
 	/* Eth + IPh + UDPh + mpls */
 	datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
-		  pkt_dev->nr_labels*sizeof(u32);
+		  pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
 	if (datalen < sizeof(struct pktgen_hdr))
 		datalen = sizeof(struct pktgen_hdr);
 
@@ -2136,7 +2387,7 @@
 	iph->ihl = 5;
 	iph->version = 4;
 	iph->ttl = 32;
-	iph->tos = 0;
+	iph->tos = pkt_dev->tos;
 	iph->protocol = IPPROTO_UDP;	/* UDP */
 	iph->saddr = pkt_dev->cur_saddr;
 	iph->daddr = pkt_dev->cur_daddr;
@@ -2146,7 +2397,8 @@
 	iph->check = 0;
 	iph->check = ip_fast_csum((void *)iph, iph->ihl);
 	skb->protocol = protocol;
-	skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
+	skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32) -
+		VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
 	skb->nh.iph = iph;
@@ -2218,7 +2470,6 @@
 		pgh->tv_sec = htonl(timestamp.tv_sec);
 		pgh->tv_usec = htonl(timestamp.tv_usec);
 	}
-	pkt_dev->seq_num++;
 
 	return skb;
 }
@@ -2402,17 +2653,26 @@
 	struct pktgen_hdr *pgh = NULL;
 	__be16 protocol = __constant_htons(ETH_P_IPV6);
 	__be32 *mpls;
+	__be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
+	__be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
+	__be16 *svlan_tci = NULL;                /* Encapsulates priority and SVLAN ID */
+	__be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
 
 	if (pkt_dev->nr_labels)
 		protocol = __constant_htons(ETH_P_MPLS_UC);
 
+	if (pkt_dev->vlan_id != 0xffff)
+		protocol = __constant_htons(ETH_P_8021Q);
+
 	/* Update any of the values, used when we're incrementing various
 	 * fields.
 	 */
 	mod_cur_headers(pkt_dev);
 
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
-			pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
+			pkt_dev->nr_labels*sizeof(u32) +
+			VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
+			GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -2425,16 +2685,34 @@
 	mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
 	if (pkt_dev->nr_labels)
 		mpls_push(mpls, pkt_dev);
+
+	if (pkt_dev->vlan_id != 0xffff) {
+		if(pkt_dev->svlan_id != 0xffff) {
+			svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+			*svlan_tci = htons(pkt_dev->svlan_id);
+			*svlan_tci |= pkt_dev->svlan_p << 5;
+			*svlan_tci |= pkt_dev->svlan_cfi << 4;
+			svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+			*svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
+		}
+		vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+		*vlan_tci = htons(pkt_dev->vlan_id);
+		*vlan_tci |= pkt_dev->vlan_p << 5;
+		*vlan_tci |= pkt_dev->vlan_cfi << 4;
+		vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+		*vlan_encapsulated_proto = __constant_htons(ETH_P_IPV6);
+	}
+
 	iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
 	udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
 
 	memcpy(eth, pkt_dev->hh, 12);
-	*(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
+	*(u16 *) & eth[12] = protocol;
 
 	/* Eth + IPh + UDPh + mpls */
 	datalen = pkt_dev->cur_pkt_size - 14 -
 		  sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
-		  pkt_dev->nr_labels*sizeof(u32);
+		  pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
 
 	if (datalen < sizeof(struct pktgen_hdr)) {
 		datalen = sizeof(struct pktgen_hdr);
@@ -2450,6 +2728,11 @@
 
 	*(u32 *) iph = __constant_htonl(0x60000000);	/* Version + flow */
 
+	if (pkt_dev->traffic_class) {
+		/* Version + traffic class + flow (0) */
+		*(u32 *)iph |= htonl(0x60000000 | (pkt_dev->traffic_class << 20));
+	}
+
 	iph->hop_limit = 32;
 
 	iph->payload_len = htons(sizeof(struct udphdr) + datalen);
@@ -2458,7 +2741,8 @@
 	ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
 	ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
 
-	skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
+	skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32) -
+		VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
 	skb->protocol = protocol;
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
@@ -2531,7 +2815,7 @@
 		pgh->tv_sec = htonl(timestamp.tv_sec);
 		pgh->tv_usec = htonl(timestamp.tv_usec);
 	}
-	pkt_dev->seq_num++;
+	/* pkt_dev->seq_num++; FF: you really mean this? */
 
 	return skb;
 }
@@ -3177,6 +3461,13 @@
 	pkt_dev->udp_dst_min = 9;
 	pkt_dev->udp_dst_max = 9;
 
+	pkt_dev->vlan_p = 0;
+	pkt_dev->vlan_cfi = 0;
+	pkt_dev->vlan_id = 0xffff;
+	pkt_dev->svlan_p = 0;
+	pkt_dev->svlan_cfi = 0;
+	pkt_dev->svlan_id = 0xffff;
+
 	strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
 
 	if (!pktgen_setup_dev(pkt_dev)) {
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d8e25e0..221e403 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -562,7 +562,7 @@
 
 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
 	if (err < 0)
-		goto errout;
+		return err;
 
 	ifm = nlmsg_data(nlh);
 	if (ifm->ifi_index >= 0) {
diff --git a/net/core/utils.c b/net/core/utils.c
index 2682490..94c5d76 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -3,7 +3,7 @@
  *
  *	Authors:
  *	net_random Alan Cox
- *	net_ratelimit Andy Kleen
+ *	net_ratelimit Andi Kleen
  *	in{4,6}_pton YOSHIFUJI Hideaki, Copyright (C)2006 USAGI/WIDE Project
  *
  *	Created by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 3168fca..ffff0da 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -68,6 +68,14 @@
  *
  * v8 - 17.02.06 - Jean II
  *	o RtNetlink requests support (SET/GET)
+ *
+ * v8b - 03.08.06 - Herbert Xu
+ *	o Fix Wireless Event locking issues.
+ *
+ * v9 - 14.3.06 - Jean II
+ *	o Change length in ESSID and NICK to strlen() instead of strlen()+1
+ *	o Make standard_ioctl_num and standard_event_num unsigned
+ *	o Remove (struct net_device *)->get_wireless_stats()
  */
 
 /***************************** INCLUDES *****************************/
@@ -234,24 +242,24 @@
 	[SIOCSIWESSID	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= 1,
-		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE,
 		.flags		= IW_DESCR_FLAG_EVENT,
 	},
 	[SIOCGIWESSID	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= 1,
-		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE,
 		.flags		= IW_DESCR_FLAG_DUMP,
 	},
 	[SIOCSIWNICKN	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= 1,
-		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE,
 	},
 	[SIOCGIWNICKN	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= 1,
-		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE,
 	},
 	[SIOCSIWRATE	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_PARAM,
@@ -338,8 +346,8 @@
 		.max_tokens	= sizeof(struct iw_pmksa),
 	},
 };
-static const int standard_ioctl_num = (sizeof(standard_ioctl) /
-				       sizeof(struct iw_ioctl_description));
+static const unsigned standard_ioctl_num = (sizeof(standard_ioctl) /
+					    sizeof(struct iw_ioctl_description));
 
 /*
  * Meta-data about all the additional standard Wireless Extension events
@@ -389,8 +397,8 @@
 		.max_tokens	= sizeof(struct iw_pmkid_cand),
 	},
 };
-static const int standard_event_num = (sizeof(standard_event) /
-				       sizeof(struct iw_ioctl_description));
+static const unsigned standard_event_num = (sizeof(standard_event) /
+					    sizeof(struct iw_ioctl_description));
 
 /* Size (in bytes) of the various private data types */
 static const char iw_priv_type_size[] = {
@@ -465,17 +473,6 @@
 	   (dev->wireless_handlers->get_wireless_stats != NULL))
 		return dev->wireless_handlers->get_wireless_stats(dev);
 
-	/* Old location, field to be removed in next WE */
-	if(dev->get_wireless_stats) {
-		static int printed_message;
-
-		if (!printed_message++)
-			printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n",
-				dev->name);
-
-		return dev->get_wireless_stats(dev);
-	}
-
 	/* Not found */
 	return (struct iw_statistics *) NULL;
 }
@@ -1843,8 +1840,33 @@
  */
 
 #ifdef WE_EVENT_RTNETLINK
+/* ---------------------------------------------------------------- */
+/*
+ * Locking...
+ * ----------
+ *
+ * Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
+ * the locking issue in here and implementing this code !
+ *
+ * The issue : wireless_send_event() is often called in interrupt context,
+ * while the Netlink layer can never be called in interrupt context.
+ * The fully formed RtNetlink events are queued, and then a tasklet is run
+ * to feed those to Netlink.
+ * The skb_queue is interrupt safe, and its lock is not held while calling
+ * Netlink, so there is no possibility of dealock.
+ * Jean II
+ */
+
 static struct sk_buff_head wireless_nlevent_queue;
 
+static int __init wireless_nlevent_init(void)
+{
+	skb_queue_head_init(&wireless_nlevent_queue);
+	return 0;
+}
+
+subsys_initcall(wireless_nlevent_init);
+
 static void wireless_nlevent_process(unsigned long data)
 {
 	struct sk_buff *skb;
@@ -1921,13 +1943,6 @@
 	tasklet_schedule(&wireless_nlevent_tasklet);
 }
 
-static int __init wireless_nlevent_init(void)
-{
-	skb_queue_head_init(&wireless_nlevent_queue);
-	return 0;
-}
-
-subsys_initcall(wireless_nlevent_init);
 #endif	/* WE_EVENT_RTNETLINK */
 
 /* ---------------------------------------------------------------- */
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 66be29b..bf692c1 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -50,7 +50,7 @@
 	struct dccp_sock *dp = dccp_sk(sk);
 	const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
 	struct rtable *rt;
-	u32 daddr, nexthop;
+	__be32 daddr, nexthop;
 	int tmp;
 	int err;
 
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 4386393..4bd78c8 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -223,7 +223,7 @@
  */
 int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
 {
-	unsigned short type = hh->hh_type;
+	__be16 type = hh->hh_type;
 	struct ethhdr *eth;
 	struct net_device *dev = neigh->dev;
 
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 75320b6..2aa779d 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -80,10 +80,10 @@
 	 * If it's our network, ignore the change, we're already doing it!
 	 */
 	if((sm->associnfo.associating || sm->associated) &&
-	   (data->essid.flags && data->essid.length && extra)) {
+	   (data->essid.flags && data->essid.length)) {
 		/* Get the associating network */
 		n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
-		if(n && n->essid.len == (data->essid.length - 1) &&
+		if(n && n->essid.len == data->essid.length &&
 		   !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));
@@ -109,8 +109,8 @@
 	sm->associnfo.static_essid = 0;
 	sm->associnfo.assoc_wait = 0;
 
-	if (data->essid.flags && data->essid.length && extra /*required?*/) {
-		length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
+	if (data->essid.flags && data->essid.length) {
+		length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
 		if (length) {
 			memcpy(sm->associnfo.req_essid.data, extra, length);
 			sm->associnfo.static_essid = 1;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index fdd89e3..edcf093 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -996,7 +996,7 @@
 	struct rtable *rt;
 	__u32 old_saddr = inet->saddr;
 	__u32 new_saddr;
-	__u32 daddr = inet->daddr;
+	__be32 daddr = inet->daddr;
 
 	if (inet->opt && inet->opt->srr)
 		daddr = inet->opt->faddr;
@@ -1043,7 +1043,7 @@
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
-	u32 daddr;
+	__be32 daddr;
 	int err;
 
 	/* Route is OK, nothing to do. */
@@ -1342,10 +1342,10 @@
 	rc = 0;
 out:
 	return rc;
-out_unregister_tcp_proto:
-	proto_unregister(&tcp_prot);
 out_unregister_udp_proto:
 	proto_unregister(&udp_prot);
+out_unregister_tcp_proto:
+	proto_unregister(&tcp_prot);
 	goto out;
 }
 
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index c8a3723..cfe5c84 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -234,7 +234,7 @@
 
 static int arp_constructor(struct neighbour *neigh)
 {
-	u32 addr = *(u32*)neigh->primary_key;
+	__be32 addr = *(__be32*)neigh->primary_key;
 	struct net_device *dev = neigh->dev;
 	struct in_device *in_dev;
 	struct neigh_parms *parms;
@@ -330,10 +330,10 @@
 
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
-	u32 saddr = 0;
+	__be32 saddr = 0;
 	u8  *dst_ha = NULL;
 	struct net_device *dev = neigh->dev;
-	u32 target = *(u32*)neigh->primary_key;
+	__be32 target = *(__be32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
 	struct in_device *in_dev = in_dev_get(dev);
 
@@ -385,7 +385,7 @@
 }
 
 static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
-		      u32 sip, u32 tip)
+		      __be32 sip, __be32 tip)
 {
 	int scope;
 
@@ -420,7 +420,7 @@
 	return !inet_confirm_addr(dev, sip, tip, scope);
 }
 
-static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
+static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
 {
 	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip,
 						 .saddr = tip } } };
@@ -449,7 +449,7 @@
  *	is allowed to use this function, it is scheduled to be removed. --ANK
  */
 
-static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct net_device * dev)
+static int arp_set_predefined(int addr_hint, unsigned char * haddr, __be32 paddr, struct net_device * dev)
 {
 	switch (addr_hint) {
 	case RTN_LOCAL:
@@ -470,7 +470,7 @@
 int arp_find(unsigned char *haddr, struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
-	u32 paddr;
+	__be32 paddr;
 	struct neighbour *n;
 
 	if (!skb->dst) {
@@ -511,7 +511,7 @@
 	if (dev == NULL)
 		return -EINVAL;
 	if (n == NULL) {
-		u32 nexthop = ((struct rtable*)dst)->rt_gateway;
+		__be32 nexthop = ((struct rtable*)dst)->rt_gateway;
 		if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
 			nexthop = 0;
 		n = __neigh_lookup_errno(
@@ -560,8 +560,8 @@
  *	Create an arp packet. If (dest_hw == NULL), we create a broadcast
  *	message.
  */
-struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
-			   struct net_device *dev, u32 src_ip,
+struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+			   struct net_device *dev, __be32 src_ip,
 			   unsigned char *dest_hw, unsigned char *src_hw,
 			   unsigned char *target_hw)
 {
@@ -675,8 +675,8 @@
 /*
  *	Create and send an arp packet.
  */
-void arp_send(int type, int ptype, u32 dest_ip, 
-	      struct net_device *dev, u32 src_ip, 
+void arp_send(int type, int ptype, __be32 dest_ip,
+	      struct net_device *dev, __be32 src_ip,
 	      unsigned char *dest_hw, unsigned char *src_hw,
 	      unsigned char *target_hw)
 {
@@ -710,7 +710,7 @@
 	unsigned char *arp_ptr;
 	struct rtable *rt;
 	unsigned char *sha, *tha;
-	u32 sip, tip;
+	__be32 sip, tip;
 	u16 dev_type = dev->type;
 	int addr_type;
 	struct neighbour *n;
@@ -969,13 +969,13 @@
 
 static int arp_req_set(struct arpreq *r, struct net_device * dev)
 {
-	u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
 	struct neighbour *neigh;
 	int err;
 
 	if (r->arp_flags&ATF_PUBL) {
-		u32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
-		if (mask && mask != 0xFFFFFFFF)
+		__be32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
+		if (mask && mask != htonl(0xFFFFFFFF))
 			return -EINVAL;
 		if (!dev && (r->arp_flags & ATF_COM)) {
 			dev = dev_getbyhwaddr(r->arp_ha.sa_family, r->arp_ha.sa_data);
@@ -1063,7 +1063,7 @@
 
 static int arp_req_get(struct arpreq *r, struct net_device *dev)
 {
-	u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+	__be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
 	struct neighbour *neigh;
 	int err = -ENXIO;
 
@@ -1084,13 +1084,13 @@
 static int arp_req_delete(struct arpreq *r, struct net_device * dev)
 {
 	int err;
-	u32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
+	__be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
 	struct neighbour *neigh;
 
 	if (r->arp_flags & ATF_PUBL) {
-		u32 mask =
+		__be32 mask =
 		       ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
-		if (mask == 0xFFFFFFFF)
+		if (mask == htonl(0xFFFFFFFF))
 			return pneigh_delete(&arp_tbl, &ip, dev);
 		if (mask == 0) {
 			if (dev == NULL) {
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index e6ce0b3..c4e469f 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -474,6 +474,7 @@
 /**
  * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
  * @doi: the DOI value
+ * @audit_secid: the LSM secid to use in the audit message
  * @callback: the DOI cleanup/free callback
  *
  * Description:
@@ -483,7 +484,9 @@
  * success and negative values on failure.
  *
  */
-int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head))
+int cipso_v4_doi_remove(u32 doi,
+			u32 audit_secid,
+			void (*callback) (struct rcu_head * head))
 {
 	struct cipso_v4_doi *doi_def;
 	struct cipso_v4_domhsh_entry *dom_iter;
@@ -502,7 +505,8 @@
 		spin_unlock(&cipso_v4_doi_list_lock);
 		list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
 			if (dom_iter->valid)
-				netlbl_domhsh_remove(dom_iter->domain);
+				netlbl_domhsh_remove(dom_iter->domain,
+						     audit_secid);
 		cipso_v4_cache_invalidate();
 		rcu_read_unlock();
 
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index ec5da4f..7b068a8 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -25,7 +25,7 @@
 	struct inet_sock *inet = inet_sk(sk);
 	struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
 	struct rtable *rt;
-	u32 saddr;
+	__be32 saddr;
 	int oif;
 	int err;
 
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 8e8d1f1..7602c79 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -224,7 +224,7 @@
 	call_rcu(&in_dev->rcu_head, in_dev_rcu_put);
 }
 
-int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
+int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
 {
 	rcu_read_lock();
 	for_primary_ifa(in_dev) {
@@ -429,8 +429,8 @@
 
 /* Called only from RTNL semaphored context. No locks. */
 
-struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix,
-				    u32 mask)
+struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
+				    __be32 mask)
 {
 	ASSERT_RTNL();
 
@@ -467,7 +467,7 @@
 	for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 	     ifap = &ifa->ifa_next) {
 		if (tb[IFA_LOCAL] &&
-		    ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL]))
+		    ifa->ifa_local != nla_get_be32(tb[IFA_LOCAL]))
 			continue;
 
 		if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
@@ -475,7 +475,7 @@
 
 		if (tb[IFA_ADDRESS] &&
 		    (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
-		    !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa)))
+		    !inet_ifa_match(nla_get_be32(tb[IFA_ADDRESS]), ifa)))
 			continue;
 
 		__inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid);
@@ -540,14 +540,14 @@
 	ifa->ifa_scope = ifm->ifa_scope;
 	ifa->ifa_dev = in_dev;
 
-	ifa->ifa_local = nla_get_u32(tb[IFA_LOCAL]);
-	ifa->ifa_address = nla_get_u32(tb[IFA_ADDRESS]);
+	ifa->ifa_local = nla_get_be32(tb[IFA_LOCAL]);
+	ifa->ifa_address = nla_get_be32(tb[IFA_ADDRESS]);
 
 	if (tb[IFA_BROADCAST])
-		ifa->ifa_broadcast = nla_get_u32(tb[IFA_BROADCAST]);
+		ifa->ifa_broadcast = nla_get_be32(tb[IFA_BROADCAST]);
 
 	if (tb[IFA_ANYCAST])
-		ifa->ifa_anycast = nla_get_u32(tb[IFA_ANYCAST]);
+		ifa->ifa_anycast = nla_get_be32(tb[IFA_ANYCAST]);
 
 	if (tb[IFA_LABEL])
 		nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
@@ -805,7 +805,7 @@
 			break;
 		ret = 0;
 		if (ifa->ifa_mask != sin->sin_addr.s_addr) {
-			u32 old_mask = ifa->ifa_mask;
+			__be32 old_mask = ifa->ifa_mask;
 			inet_del_ifa(in_dev, ifap, 0);
 			ifa->ifa_mask = sin->sin_addr.s_addr;
 			ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
@@ -876,9 +876,9 @@
 	return done;
 }
 
-u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
+__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
 {
-	u32 addr = 0;
+	__be32 addr = 0;
 	struct in_device *in_dev;
 
 	rcu_read_lock();
@@ -927,11 +927,11 @@
 	return addr;
 }
 
-static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
-			      u32 local, int scope)
+static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst,
+			      __be32 local, int scope)
 {
 	int same = 0;
-	u32 addr = 0;
+	__be32 addr = 0;
 
 	for_ifa(in_dev) {
 		if (!addr &&
@@ -971,9 +971,9 @@
  * - local: address, 0=autoselect the local address
  * - scope: maximum allowed scope value for the local address
  */
-u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope)
+__be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope)
 {
-	u32 addr = 0;
+	__be32 addr = 0;
 	struct in_device *in_dev;
 
 	if (dev) {
@@ -1138,16 +1138,16 @@
 	ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
 
 	if (ifa->ifa_address)
-		NLA_PUT_U32(skb, IFA_ADDRESS, ifa->ifa_address);
+		NLA_PUT_BE32(skb, IFA_ADDRESS, ifa->ifa_address);
 
 	if (ifa->ifa_local)
-		NLA_PUT_U32(skb, IFA_LOCAL, ifa->ifa_local);
+		NLA_PUT_BE32(skb, IFA_LOCAL, ifa->ifa_local);
 
 	if (ifa->ifa_broadcast)
-		NLA_PUT_U32(skb, IFA_BROADCAST, ifa->ifa_broadcast);
+		NLA_PUT_BE32(skb, IFA_BROADCAST, ifa->ifa_broadcast);
 
 	if (ifa->ifa_anycast)
-		NLA_PUT_U32(skb, IFA_ANYCAST, ifa->ifa_anycast);
+		NLA_PUT_BE32(skb, IFA_ANYCAST, ifa->ifa_anycast);
 
 	if (ifa->ifa_label[0])
 		NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index cfb527c..9c399a7 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -122,7 +122,7 @@
  *	Find the first device with a given source address.
  */
 
-struct net_device * ip_dev_find(u32 addr)
+struct net_device * ip_dev_find(__be32 addr)
 {
 	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
 	struct fib_result res;
@@ -146,7 +146,7 @@
 	return dev;
 }
 
-unsigned inet_addr_type(u32 addr)
+unsigned inet_addr_type(__be32 addr)
 {
 	struct flowi		fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
 	struct fib_result	res;
@@ -180,8 +180,8 @@
    - check, that packet arrived from expected physical interface.
  */
 
-int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-			struct net_device *dev, u32 *spec_dst, u32 *itag)
+int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
+			struct net_device *dev, __be32 *spec_dst, u32 *itag)
 {
 	struct in_device *in_dev;
 	struct flowi fl = { .nl_u = { .ip4_u =
@@ -253,7 +253,7 @@
 
 #ifndef CONFIG_IP_NOSIOCRT
 
-static inline u32 sk_extract_addr(struct sockaddr *addr)
+static inline __be32 sk_extract_addr(struct sockaddr *addr)
 {
 	return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
 }
@@ -273,7 +273,7 @@
 static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
 				 struct fib_config *cfg)
 {
-	u32 addr;
+	__be32 addr;
 	int plen;
 
 	memset(cfg, 0, sizeof(*cfg));
@@ -292,7 +292,7 @@
 	plen = 32;
 	addr = sk_extract_addr(&rt->rt_dst);
 	if (!(rt->rt_flags & RTF_HOST)) {
-		u32 mask = sk_extract_addr(&rt->rt_genmask);
+		__be32 mask = sk_extract_addr(&rt->rt_genmask);
 
 		if (rt->rt_genmask.sa_family != AF_INET) {
 			if (mask || rt->rt_genmask.sa_family)
@@ -499,22 +499,22 @@
 	nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
 		switch (attr->nla_type) {
 		case RTA_DST:
-			cfg->fc_dst = nla_get_u32(attr);
+			cfg->fc_dst = nla_get_be32(attr);
 			break;
 		case RTA_SRC:
-			cfg->fc_src = nla_get_u32(attr);
+			cfg->fc_src = nla_get_be32(attr);
 			break;
 		case RTA_OIF:
 			cfg->fc_oif = nla_get_u32(attr);
 			break;
 		case RTA_GATEWAY:
-			cfg->fc_gw = nla_get_u32(attr);
+			cfg->fc_gw = nla_get_be32(attr);
 			break;
 		case RTA_PRIORITY:
 			cfg->fc_priority = nla_get_u32(attr);
 			break;
 		case RTA_PREFSRC:
-			cfg->fc_prefsrc = nla_get_u32(attr);
+			cfg->fc_prefsrc = nla_get_be32(attr);
 			break;
 		case RTA_METRICS:
 			cfg->fc_mx = nla_data(attr);
@@ -627,8 +627,7 @@
    only when netlink is already locked.
  */
 
-static void fib_magic(int cmd, int type, u32 dst, int dst_len,
-		      struct in_ifaddr *ifa)
+static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
 {
 	struct fib_table *tb;
 	struct fib_config cfg = {
@@ -667,9 +666,9 @@
 	struct in_device *in_dev = ifa->ifa_dev;
 	struct net_device *dev = in_dev->dev;
 	struct in_ifaddr *prim = ifa;
-	u32 mask = ifa->ifa_mask;
-	u32 addr = ifa->ifa_local;
-	u32 prefix = ifa->ifa_address&mask;
+	__be32 mask = ifa->ifa_mask;
+	__be32 addr = ifa->ifa_local;
+	__be32 prefix = ifa->ifa_address&mask;
 
 	if (ifa->ifa_flags&IFA_F_SECONDARY) {
 		prim = inet_ifa_byprefix(in_dev, prefix, mask);
@@ -685,7 +684,7 @@
 		return;
 
 	/* Add broadcast address, if it is explicitly assigned. */
-	if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)
+	if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
 		fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
 
 	if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
@@ -707,8 +706,8 @@
 	struct net_device *dev = in_dev->dev;
 	struct in_ifaddr *ifa1;
 	struct in_ifaddr *prim = ifa;
-	u32 brd = ifa->ifa_address|~ifa->ifa_mask;
-	u32 any = ifa->ifa_address&ifa->ifa_mask;
+	__be32 brd = ifa->ifa_address|~ifa->ifa_mask;
+	__be32 any = ifa->ifa_address&ifa->ifa_mask;
 #define LOCAL_OK	1
 #define BRD_OK		2
 #define BRD0_OK		4
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 88133b3..107bb6c 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -51,7 +51,7 @@
 struct fib_node {
 	struct hlist_node	fn_hash;
 	struct list_head	fn_alias;
-	u32			fn_key;
+	__be32			fn_key;
 };
 
 struct fn_zone {
@@ -64,7 +64,7 @@
 #define FZ_HASHMASK(fz)		((fz)->fz_hashmask)
 
 	int			fz_order;	/* Zone order		*/
-	u32			fz_mask;
+	__be32			fz_mask;
 #define FZ_MASK(fz)		((fz)->fz_mask)
 };
 
@@ -77,7 +77,7 @@
 	struct fn_zone	*fn_zone_list;
 };
 
-static inline u32 fn_hash(u32 key, struct fn_zone *fz)
+static inline u32 fn_hash(__be32 key, struct fn_zone *fz)
 {
 	u32 h = ntohl(key)>>(32 - fz->fz_order);
 	h ^= (h>>20);
@@ -87,7 +87,7 @@
 	return h;
 }
 
-static inline u32 fz_key(u32 dst, struct fn_zone *fz)
+static inline __be32 fz_key(__be32 dst, struct fn_zone *fz)
 {
 	return dst & FZ_MASK(fz);
 }
@@ -254,7 +254,7 @@
 		struct hlist_head *head;
 		struct hlist_node *node;
 		struct fib_node *f;
-		u32 k = fz_key(flp->fl4_dst, fz);
+		__be32 k = fz_key(flp->fl4_dst, fz);
 
 		head = &fz->fz_hash[fn_hash(k, fz)];
 		hlist_for_each_entry(f, node, head, fn_hash) {
@@ -365,7 +365,7 @@
 }
 
 /* Return the node in FZ matching KEY. */
-static struct fib_node *fib_find_node(struct fn_zone *fz, u32 key)
+static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key)
 {
 	struct hlist_head *head = &fz->fz_hash[fn_hash(key, fz)];
 	struct hlist_node *node;
@@ -387,7 +387,7 @@
 	struct fn_zone *fz;
 	struct fib_info *fi;
 	u8 tos = cfg->fc_tos;
-	u32 key;
+	__be32 key;
 	int err;
 
 	if (cfg->fc_dst_len > 32)
@@ -541,7 +541,7 @@
 	struct fib_node *f;
 	struct fib_alias *fa, *fa_to_delete;
 	struct fn_zone *fz;
-	u32 key;
+	__be32 key;
 
 	if (cfg->fc_dst_len > 32)
 		return -EINVAL;
@@ -966,7 +966,7 @@
 	read_unlock(&fib_hash_lock);
 }
 
-static unsigned fib_flag_trans(int type, u32 mask, struct fib_info *fi)
+static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi)
 {
 	static const unsigned type2flags[RTN_MAX + 1] = {
 		[7] = RTF_REJECT, [8] = RTF_REJECT,
@@ -975,7 +975,7 @@
 
 	if (fi && fi->fib_nh->nh_gw)
 		flags |= RTF_GATEWAY;
-	if (mask == 0xFFFFFFFF)
+	if (mask == htonl(0xFFFFFFFF))
 		flags |= RTF_HOST;
 	flags |= RTF_UP;
 	return flags;
@@ -991,7 +991,7 @@
 {
 	struct fib_iter_state *iter;
 	char bf[128];
-	u32 prefix, mask;
+	__be32 prefix, mask;
 	unsigned flags;
 	struct fib_node *f;
 	struct fib_alias *fa;
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index fd6f776..0e8b70b 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -20,16 +20,16 @@
 /* Exported by fib_semantics.c */
 extern int fib_semantic_match(struct list_head *head,
 			      const struct flowi *flp,
-			      struct fib_result *res, __u32 zone, __u32 mask,
+			      struct fib_result *res, __be32 zone, __be32 mask,
 				int prefixlen);
 extern void fib_release_info(struct fib_info *);
 extern struct fib_info *fib_create_info(struct fib_config *cfg);
 extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-			 u32 tb_id, u8 type, u8 scope, u32 dst,
+			 u32 tb_id, u8 type, u8 scope, __be32 dst,
 			 int dst_len, u8 tos, struct fib_info *fi,
 			 unsigned int);
-extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
+extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 		      int dst_len, u32 tb_id, struct nl_info *info);
 extern struct fib_alias *fib_find_alias(struct list_head *fah,
 					u8 tos, u32 prio);
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 52b2ada..0852b9c 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -40,10 +40,10 @@
 	u8			dst_len;
 	u8			src_len;
 	u8			tos;
-	u32			src;
-	u32			srcmask;
-	u32			dst;
-	u32			dstmask;
+	__be32			src;
+	__be32			srcmask;
+	__be32			dst;
+	__be32			dstmask;
 #ifdef CONFIG_IP_ROUTE_FWMARK
 	u32			fwmark;
 	u32			fwmask;
@@ -150,8 +150,8 @@
 static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 {
 	struct fib4_rule *r = (struct fib4_rule *) rule;
-	u32 daddr = fl->fl4_dst;
-	u32 saddr = fl->fl4_src;
+	__be32 daddr = fl->fl4_dst;
+	__be32 saddr = fl->fl4_src;
 
 	if (((saddr ^ r->src) & r->srcmask) ||
 	    ((daddr ^ r->dst) & r->dstmask))
@@ -215,10 +215,10 @@
 	}
 
 	if (tb[FRA_SRC])
-		rule4->src = nla_get_u32(tb[FRA_SRC]);
+		rule4->src = nla_get_be32(tb[FRA_SRC]);
 
 	if (tb[FRA_DST])
-		rule4->dst = nla_get_u32(tb[FRA_DST]);
+		rule4->dst = nla_get_be32(tb[FRA_DST]);
 
 #ifdef CONFIG_IP_ROUTE_FWMARK
 	if (tb[FRA_FWMARK]) {
@@ -277,10 +277,10 @@
 		return 0;
 #endif
 
-	if (tb[FRA_SRC] && (rule4->src != nla_get_u32(tb[FRA_SRC])))
+	if (tb[FRA_SRC] && (rule4->src != nla_get_be32(tb[FRA_SRC])))
 		return 0;
 
-	if (tb[FRA_DST] && (rule4->dst != nla_get_u32(tb[FRA_DST])))
+	if (tb[FRA_DST] && (rule4->dst != nla_get_be32(tb[FRA_DST])))
 		return 0;
 
 	return 1;
@@ -305,10 +305,10 @@
 #endif
 
 	if (rule4->dst_len)
-		NLA_PUT_U32(skb, FRA_DST, rule4->dst);
+		NLA_PUT_BE32(skb, FRA_DST, rule4->dst);
 
 	if (rule4->src_len)
-		NLA_PUT_U32(skb, FRA_SRC, rule4->src);
+		NLA_PUT_BE32(skb, FRA_SRC, rule4->src);
 
 #ifdef CONFIG_NET_CLS_ROUTE
 	if (rule4->tclassid)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 2ead0954..884d176 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -203,7 +203,7 @@
 	unsigned int val = fi->fib_nhs;
 
 	val ^= fi->fib_protocol;
-	val ^= fi->fib_prefsrc;
+	val ^= (__force u32)fi->fib_prefsrc;
 	val ^= fi->fib_priority;
 
 	return (val ^ (val >> 7) ^ (val >> 12)) & mask;
@@ -248,7 +248,7 @@
    Used only by redirect accept routine.
  */
 
-int ip_fib_check_default(u32 gw, struct net_device *dev)
+int ip_fib_check_default(__be32 gw, struct net_device *dev)
 {
 	struct hlist_head *head;
 	struct hlist_node *node;
@@ -273,7 +273,7 @@
 	return -1;
 }
 
-void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
+void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 	       int dst_len, u32 tb_id, struct nl_info *info)
 {
 	struct sk_buff *skb;
@@ -374,7 +374,7 @@
 			struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
 
 			nla = nla_find(attrs, attrlen, RTA_GATEWAY);
-			nh->nh_gw = nla ? nla_get_u32(nla) : 0;
+			nh->nh_gw = nla ? nla_get_be32(nla) : 0;
 #ifdef CONFIG_NET_CLS_ROUTE
 			nla = nla_find(attrs, attrlen, RTA_FLOW);
 			nh->nh_tclassid = nla ? nla_get_u32(nla) : 0;
@@ -427,7 +427,7 @@
 			struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
 
 			nla = nla_find(attrs, attrlen, RTA_GATEWAY);
-			if (nla && nla_get_u32(nla) != nh->nh_gw)
+			if (nla && nla_get_be32(nla) != nh->nh_gw)
 				return 1;
 #ifdef CONFIG_NET_CLS_ROUTE
 			nla = nla_find(attrs, attrlen, RTA_FLOW);
@@ -568,11 +568,11 @@
 	return 0;
 }
 
-static inline unsigned int fib_laddr_hashfn(u32 val)
+static inline unsigned int fib_laddr_hashfn(__be32 val)
 {
 	unsigned int mask = (fib_hash_size - 1);
 
-	return (val ^ (val >> 7) ^ (val >> 14)) & mask;
+	return ((__force u32)val ^ ((__force u32)val >> 7) ^ ((__force u32)val >> 14)) & mask;
 }
 
 static struct hlist_head *fib_hash_alloc(int bytes)
@@ -847,7 +847,7 @@
 
 /* Note! fib_semantic_match intentionally uses  RCU list functions. */
 int fib_semantic_match(struct list_head *head, const struct flowi *flp,
-		       struct fib_result *res, __u32 zone, __u32 mask, 
+		       struct fib_result *res, __be32 zone, __be32 mask,
 			int prefixlen)
 {
 	struct fib_alias *fa;
@@ -914,8 +914,7 @@
 	res->fi = fa->fa_info;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
 	res->netmask = mask;
-	res->network = zone &
-		(0xFFFFFFFF >> (32 - prefixlen));
+	res->network = zone & inet_make_mask(prefixlen);
 #endif
 	atomic_inc(&res->fi->fib_clntref);
 	return 0;
@@ -923,13 +922,13 @@
 
 /* Find appropriate source address to this destination */
 
-u32 __fib_res_prefsrc(struct fib_result *res)
+__be32 __fib_res_prefsrc(struct fib_result *res)
 {
 	return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
 }
 
 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-		  u32 tb_id, u8 type, u8 scope, u32 dst, int dst_len, u8 tos,
+		  u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos,
 		  struct fib_info *fi, unsigned int flags)
 {
 	struct nlmsghdr *nlh;
@@ -952,7 +951,7 @@
 	rtm->rtm_protocol = fi->fib_protocol;
 
 	if (rtm->rtm_dst_len)
-		NLA_PUT_U32(skb, RTA_DST, dst);
+		NLA_PUT_BE32(skb, RTA_DST, dst);
 
 	if (fi->fib_priority)
 		NLA_PUT_U32(skb, RTA_PRIORITY, fi->fib_priority);
@@ -961,11 +960,11 @@
 		goto nla_put_failure;
 
 	if (fi->fib_prefsrc)
-		NLA_PUT_U32(skb, RTA_PREFSRC, fi->fib_prefsrc);
+		NLA_PUT_BE32(skb, RTA_PREFSRC, fi->fib_prefsrc);
 
 	if (fi->fib_nhs == 1) {
 		if (fi->fib_nh->nh_gw)
-			NLA_PUT_U32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw);
+			NLA_PUT_BE32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw);
 
 		if (fi->fib_nh->nh_oif)
 			NLA_PUT_U32(skb, RTA_OIF, fi->fib_nh->nh_oif);
@@ -993,7 +992,7 @@
 			rtnh->rtnh_ifindex = nh->nh_oif;
 
 			if (nh->nh_gw)
-				NLA_PUT_U32(skb, RTA_GATEWAY, nh->nh_gw);
+				NLA_PUT_BE32(skb, RTA_GATEWAY, nh->nh_gw);
 #ifdef CONFIG_NET_CLS_ROUTE
 			if (nh->nh_tclassid)
 				NLA_PUT_U32(skb, RTA_FLOW, nh->nh_tclassid);
@@ -1018,7 +1017,7 @@
    - device went down -> we must shutdown all nexthops going via it.
  */
 
-int fib_sync_down(u32 local, struct net_device *dev, int force)
+int fib_sync_down(__be32 local, struct net_device *dev, int force)
 {
 	int ret = 0;
 	int scope = RT_SCOPE_NOWHERE;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 9c3ff6b..d17990e 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1834,7 +1834,7 @@
 	int i, s_i;
 	struct fib_alias *fa;
 
-	u32 xkey = htonl(key);
+	__be32 xkey = htonl(key);
 
 	s_i = cb->args[4];
 	i = 0;
@@ -2281,7 +2281,7 @@
 
 	if (IS_TNODE(n)) {
 		struct tnode *tn = (struct tnode *) n;
-		t_key prf = ntohl(MASK_PFX(tn->key, tn->pos));
+		__be32 prf = htonl(MASK_PFX(tn->key, tn->pos));
 
 		if (!NODE_PARENT(n)) {
 			if (iter->trie == trie_local)
@@ -2297,7 +2297,7 @@
 	} else {
 		struct leaf *l = (struct leaf *) n;
 		int i;
-		u32 val = ntohl(l->key);
+		__be32 val = htonl(l->key);
 
 		seq_indent(seq, iter->depth);
 		seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));
@@ -2360,7 +2360,7 @@
 	.release = seq_release_private,
 };
 
-static unsigned fib_flag_trans(int type, u32 mask, const struct fib_info *fi)
+static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
 {
 	static unsigned type2flags[RTN_MAX + 1] = {
 		[7] = RTF_REJECT, [8] = RTF_REJECT,
@@ -2369,7 +2369,7 @@
 
 	if (fi && fi->fib_nh->nh_gw)
 		flags |= RTF_GATEWAY;
-	if (mask == 0xFFFFFFFF)
+	if (mask == htonl(0xFFFFFFFF))
 		flags |= RTF_HOST;
 	flags |= RTF_UP;
 	return flags;
@@ -2403,7 +2403,7 @@
 	for (i=32; i>=0; i--) {
 		struct leaf_info *li = find_leaf_info(l, i);
 		struct fib_alias *fa;
-		u32 mask, prefix;
+		__be32 mask, prefix;
 
 		if (!li)
 			continue;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index c2ad07e..b39a37a 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -104,7 +104,7 @@
 
 	struct {
 		struct icmphdr icmph;
-		__u32	       times[3];
+		__be32	       times[3];
 	} data;
 	int head_len;
 	struct ip_options replyopts;
@@ -381,7 +381,7 @@
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipcm_cookie ipc;
 	struct rtable *rt = (struct rtable *)skb->dst;
-	u32 daddr;
+	__be32 daddr;
 
 	if (ip_options_echo(&icmp_param->replyopts, skb))
 		return;
@@ -430,14 +430,14 @@
  *			MUST reply to only the first fragment.
  */
 
-void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
+void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 {
 	struct iphdr *iph;
 	int room;
 	struct icmp_bxm icmp_param;
 	struct rtable *rt = (struct rtable *)skb_in->dst;
 	struct ipcm_cookie ipc;
-	u32 saddr;
+	__be32 saddr;
 	u8  tos;
 
 	if (!rt)
@@ -895,7 +895,7 @@
 	if (in_dev->ifa_list &&
 	    IN_DEV_LOG_MARTIANS(in_dev) &&
 	    IN_DEV_FORWARD(in_dev)) {
-		u32 _mask, *mp;
+		__be32 _mask, *mp;
 
 		mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask);
 		BUG_ON(mp == NULL);
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 58be822..6eee716 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -138,14 +138,14 @@
 		time_before(jiffies, (in_dev)->mr_v2_seen)))
 
 static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
-static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr);
+static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
 static void igmpv3_clear_delrec(struct in_device *in_dev);
 static int sf_setstate(struct ip_mc_list *pmc);
 static void sf_markstate(struct ip_mc_list *pmc);
 #endif
 static void ip_mc_clear_src(struct ip_mc_list *pmc);
-static int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
-			 int sfcount, __u32 *psfsrc, int delta);
+static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+			 int sfcount, __be32 *psfsrc, int delta);
 
 static void ip_ma_put(struct ip_mc_list *im)
 {
@@ -426,7 +426,7 @@
 	first = 1;
 	psf_prev = NULL;
 	for (psf=*psf_list; psf; psf=psf_next) {
-		u32 *psrc;
+		__be32 *psrc;
 
 		psf_next = psf->sf_next;
 
@@ -439,7 +439,7 @@
 		if (isquery)
 			psf->sf_gsresp = 0;
 
-		if (AVAILABLE(skb) < sizeof(u32) +
+		if (AVAILABLE(skb) < sizeof(__be32) +
 		    first*sizeof(struct igmpv3_grec)) {
 			if (truncate && !first)
 				break;	 /* truncate these */
@@ -455,7 +455,7 @@
 			skb = add_grhead(skb, pmc, type, &pgr);
 			first = 0;
 		}
-		psrc = (u32 *)skb_put(skb, sizeof(u32));
+		psrc = (__be32 *)skb_put(skb, sizeof(__be32));
 		*psrc = psf->sf_inaddr;
 		scount++; stotal++;
 		if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
@@ -630,8 +630,8 @@
 	struct igmphdr *ih;
 	struct rtable *rt;
 	struct net_device *dev = in_dev->dev;
-	u32	group = pmc ? pmc->multiaddr : 0;
-	u32	dst;
+	__be32	group = pmc ? pmc->multiaddr : 0;
+	__be32	dst;
 
 	if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
 		return igmpv3_send_report(in_dev, pmc);
@@ -748,7 +748,7 @@
 }
 
 /* mark EXCLUDE-mode sources */
-static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
 {
 	struct ip_sf_list *psf;
 	int i, scount;
@@ -775,7 +775,7 @@
 	return 1;
 }
 
-static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
 {
 	struct ip_sf_list *psf;
 	int i, scount;
@@ -803,7 +803,7 @@
 	return 1;
 }
 
-static void igmp_heard_report(struct in_device *in_dev, u32 group)
+static void igmp_heard_report(struct in_device *in_dev, __be32 group)
 {
 	struct ip_mc_list *im;
 
@@ -828,7 +828,7 @@
 	struct igmphdr 		*ih = skb->h.igmph;
 	struct igmpv3_query *ih3 = (struct igmpv3_query *)ih;
 	struct ip_mc_list	*im;
-	u32			group = ih->group;
+	__be32			group = ih->group;
 	int			max_delay;
 	int			mark = 0;
 
@@ -862,7 +862,7 @@
 		ih3 = (struct igmpv3_query *) skb->h.raw;
 		if (ih3->nsrcs) {
 			if (!pskb_may_pull(skb, sizeof(struct igmpv3_query) 
-					   + ntohs(ih3->nsrcs)*sizeof(__u32)))
+					   + ntohs(ih3->nsrcs)*sizeof(__be32)))
 				return;
 			ih3 = (struct igmpv3_query *) skb->h.raw;
 		}
@@ -985,7 +985,7 @@
  *	Add a filter to a device
  */
 
-static void ip_mc_filter_add(struct in_device *in_dev, u32 addr)
+static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
 {
 	char buf[MAX_ADDR_LEN];
 	struct net_device *dev = in_dev->dev;
@@ -1005,7 +1005,7 @@
  *	Remove a filter from a device
  */
 
-static void ip_mc_filter_del(struct in_device *in_dev, u32 addr)
+static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr)
 {
 	char buf[MAX_ADDR_LEN];
 	struct net_device *dev = in_dev->dev;
@@ -1055,7 +1055,7 @@
 	spin_unlock_bh(&in_dev->mc_tomb_lock);
 }
 
-static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr)
+static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
 {
 	struct ip_mc_list *pmc, *pmc_prev;
 	struct ip_sf_list *psf, *psf_next;
@@ -1193,7 +1193,7 @@
  *	A socket has joined a multicast group on device dev.
  */
 
-void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
+void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
 {
 	struct ip_mc_list *im;
 
@@ -1252,7 +1252,7 @@
  *	A socket has left a multicast group on device dev
  */
 
-void ip_mc_dec_group(struct in_device *in_dev, u32 addr)
+void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
 {
 	struct ip_mc_list *i, **ip;
 	
@@ -1402,7 +1402,7 @@
 
 
 static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
-	__u32 *psfsrc)
+	__be32 *psfsrc)
 {
 	struct ip_sf_list *psf, *psf_prev;
 	int rv = 0;
@@ -1450,8 +1450,8 @@
 #define igmp_ifc_event(x)	do { } while (0)
 #endif
 
-static int ip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
-			 int sfcount, __u32 *psfsrc, int delta)
+static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+			 int sfcount, __be32 *psfsrc, int delta)
 {
 	struct ip_mc_list *pmc;
 	int	changerec = 0;
@@ -1517,7 +1517,7 @@
  * Add multicast single-source filter to the interface list
  */
 static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
-	__u32 *psfsrc, int delta)
+	__be32 *psfsrc, int delta)
 {
 	struct ip_sf_list *psf, *psf_prev;
 
@@ -1623,8 +1623,8 @@
 /*
  * Add multicast source filter list to the interface list
  */
-static int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
-			 int sfcount, __u32 *psfsrc, int delta)
+static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+			 int sfcount, __be32 *psfsrc, int delta)
 {
 	struct ip_mc_list *pmc;
 	int	isexclude;
@@ -1717,7 +1717,7 @@
 int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
 {
 	int err;
-	u32 addr = imr->imr_multiaddr.s_addr;
+	__be32 addr = imr->imr_multiaddr.s_addr;
 	struct ip_mc_socklist *iml=NULL, *i;
 	struct in_device *in_dev;
 	struct inet_sock *inet = inet_sk(sk);
@@ -1791,7 +1791,7 @@
 	struct inet_sock *inet = inet_sk(sk);
 	struct ip_mc_socklist *iml, **imlp;
 	struct in_device *in_dev;
-	u32 group = imr->imr_multiaddr.s_addr;
+	__be32 group = imr->imr_multiaddr.s_addr;
 	u32 ifindex;
 	int ret = -EADDRNOTAVAIL;
 
@@ -1829,7 +1829,7 @@
 {
 	int err;
 	struct ip_mreqn imr;
-	u32 addr = mreqs->imr_multiaddr;
+	__be32 addr = mreqs->imr_multiaddr;
 	struct ip_mc_socklist *pmc;
 	struct in_device *in_dev = NULL;
 	struct inet_sock *inet = inet_sk(sk);
@@ -1883,7 +1883,7 @@
 		rv = !0;
 		for (i=0; i<psl->sl_count; i++) {
 			rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
-				sizeof(__u32));
+				sizeof(__be32));
 			if (rv == 0)
 				break;
 		}
@@ -1935,7 +1935,7 @@
 	rv = 1;	/* > 0 for insert logic below if sl_count is 0 */
 	for (i=0; i<psl->sl_count; i++) {
 		rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
-			sizeof(__u32));
+			sizeof(__be32));
 		if (rv == 0)
 			break;
 	}
@@ -1960,7 +1960,7 @@
 {
 	int err = 0;
 	struct ip_mreqn	imr;
-	u32 addr = msf->imsf_multiaddr;
+	__be32 addr = msf->imsf_multiaddr;
 	struct ip_mc_socklist *pmc;
 	struct in_device *in_dev;
 	struct inet_sock *inet = inet_sk(sk);
@@ -2044,7 +2044,7 @@
 {
 	int err, len, count, copycount;
 	struct ip_mreqn	imr;
-	u32 addr = msf->imsf_multiaddr;
+	__be32 addr = msf->imsf_multiaddr;
 	struct ip_mc_socklist *pmc;
 	struct in_device *in_dev;
 	struct inet_sock *inet = inet_sk(sk);
@@ -2103,7 +2103,7 @@
 {
 	int err, i, count, copycount;
 	struct sockaddr_in *psin;
-	u32 addr;
+	__be32 addr;
 	struct ip_mc_socklist *pmc;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ip_sf_socklist *psl;
@@ -2156,7 +2156,7 @@
 /*
  * check if a multicast source filter allows delivery for a given <src,dst,intf>
  */
-int ip_mc_sf_allow(struct sock *sk, u32 loc_addr, u32 rmt_addr, int dif)
+int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct ip_mc_socklist *pmc;
@@ -2216,7 +2216,7 @@
 	rtnl_unlock();
 }
 
-int ip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto)
+int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
 {
 	struct ip_mc_list *im;
 	struct ip_sf_list *psf;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 0720439..96bbe2a 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -39,7 +39,7 @@
 int inet_csk_bind_conflict(const struct sock *sk,
 			   const struct inet_bind_bucket *tb)
 {
-	const u32 sk_rcv_saddr = inet_rcv_saddr(sk);
+	const __be32 sk_rcv_saddr = inet_rcv_saddr(sk);
 	struct sock *sk2;
 	struct hlist_node *node;
 	int reuse = sk->sk_reuse;
@@ -52,7 +52,7 @@
 		     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
 			if (!reuse || !sk2->sk_reuse ||
 			    sk2->sk_state == TCP_LISTEN) {
-				const u32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
+				const __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
 				if (!sk2_rcv_saddr || !sk_rcv_saddr ||
 				    sk2_rcv_saddr == sk_rcv_saddr)
 					break;
@@ -342,10 +342,10 @@
 
 EXPORT_SYMBOL_GPL(inet_csk_route_req);
 
-static inline u32 inet_synq_hash(const u32 raddr, const u16 rport,
+static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport,
 				 const u32 rnd, const u16 synq_hsize)
 {
-	return jhash_2words(raddr, (u32)rport, rnd) & (synq_hsize - 1);
+	return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1);
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -356,8 +356,8 @@
 
 struct request_sock *inet_csk_search_req(const struct sock *sk,
 					 struct request_sock ***prevp,
-					 const __u16 rport, const __u32 raddr,
-					 const __u32 laddr)
+					 const __be16 rport, const __be32 raddr,
+					 const __be32 laddr)
 {
 	const struct inet_connection_sock *icsk = inet_csk(sk);
 	struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 492858e..77761ac 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -36,8 +36,8 @@
 static const struct inet_diag_handler **inet_diag_table;
 
 struct inet_diag_entry {
-	u32 *saddr;
-	u32 *daddr;
+	__be32 *saddr;
+	__be32 *daddr;
 	u16 sport;
 	u16 dport;
 	u16 family;
@@ -294,7 +294,7 @@
 	return err;
 }
 
-static int bitstring_match(const u32 *a1, const u32 *a2, int bits)
+static int bitstring_match(const __be32 *a1, const __be32 *a2, int bits)
 {
 	int words = bits >> 5;
 
@@ -305,8 +305,8 @@
 			return 0;
 	}
 	if (bits) {
-		__u32 w1, w2;
-		__u32 mask;
+		__be32 w1, w2;
+		__be32 mask;
 
 		w1 = a1[words];
 		w2 = a2[words];
@@ -352,7 +352,7 @@
 		case INET_DIAG_BC_S_COND:
 		case INET_DIAG_BC_D_COND: {
 			struct inet_diag_hostcond *cond;
-			u32 *addr;
+			__be32 *addr;
 
 			cond = (struct inet_diag_hostcond *)(op + 1);
 			if (cond->port != -1 &&
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index fb296c9..244c4f4 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -125,7 +125,7 @@
  * wildcarded during the search since they can never be otherwise.
  */
 static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
-					      const u32 daddr,
+					      const __be32 daddr,
 					      const unsigned short hnum,
 					      const int dif)
 {
@@ -137,7 +137,7 @@
 		const struct inet_sock *inet = inet_sk(sk);
 
 		if (inet->num == hnum && !ipv6_only_sock(sk)) {
-			const __u32 rcv_saddr = inet->rcv_saddr;
+			const __be32 rcv_saddr = inet->rcv_saddr;
 			int score = sk->sk_family == PF_INET ? 1 : 0;
 
 			if (rcv_saddr) {
@@ -163,7 +163,7 @@
 
 /* Optimize the common listener case. */
 struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
-				    const u32 daddr, const unsigned short hnum,
+				    const __be32 daddr, const unsigned short hnum,
 				    const int dif)
 {
 	struct sock *sk = NULL;
@@ -197,11 +197,11 @@
 {
 	struct inet_hashinfo *hinfo = death_row->hashinfo;
 	struct inet_sock *inet = inet_sk(sk);
-	u32 daddr = inet->rcv_saddr;
-	u32 saddr = inet->daddr;
+	__be32 daddr = inet->rcv_saddr;
+	__be32 saddr = inet->daddr;
 	int dif = sk->sk_bound_dev_if;
 	INET_ADDR_COOKIE(acookie, saddr, daddr)
-	const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+	const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
 	unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
 	struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
 	struct sock *sk2;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index a675602..2b1a54b 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -163,7 +163,7 @@
 	for (u = peer_root; u != peer_avl_empty; ) {		\
 		if (daddr == u->v4daddr)			\
 			break;					\
-		if (daddr < u->v4daddr)				\
+		if ((__force __u32)daddr < (__force __u32)u->v4daddr)	\
 			v = &u->avl_left;			\
 		else						\
 			v = &u->avl_right;			\
@@ -368,7 +368,7 @@
 }
 
 /* Called with or without local BH being disabled. */
-struct inet_peer *inet_getpeer(__u32 daddr, int create)
+struct inet_peer *inet_getpeer(__be32 daddr, int create)
 {
 	struct inet_peer *p, *n;
 	struct inet_peer **stack[PEER_MAXDEPTH], ***stackptr;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 165d728..74046ef 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -77,9 +77,9 @@
 	struct hlist_node list;
 	struct list_head lru_list;	/* lru list member 			*/
 	u32		user;
-	u32		saddr;
-	u32		daddr;
-	u16		id;
+	__be32		saddr;
+	__be32		daddr;
+	__be16		id;
 	u8		protocol;
 	u8		last_in;
 #define COMPLETE		4
@@ -123,9 +123,10 @@
 	write_unlock(&ipfrag_lock);
 }
 
-static unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
+static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
 {
-	return jhash_3words((u32)id << 16 | prot, saddr, daddr,
+	return jhash_3words((__force u32)id << 16 | prot,
+			    (__force u32)saddr, (__force u32)daddr,
 			    ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
 }
 
@@ -387,8 +388,8 @@
 static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
 {
 	__be16 id = iph->id;
-	__u32 saddr = iph->saddr;
-	__u32 daddr = iph->daddr;
+	__be32 saddr = iph->saddr;
+	__be32 daddr = iph->daddr;
 	__u8 protocol = iph->protocol;
 	unsigned int hash;
 	struct ipq *qp;
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index e7437c0..8dabbfc 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -38,7 +38,7 @@
  */
 
 void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
-			    u32 daddr, struct rtable *rt, int is_frag) 
+			    __be32 daddr, struct rtable *rt, int is_frag)
 {
 	unsigned char * iph = skb->nh.raw;
 
@@ -57,7 +57,7 @@
 			ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
 		if (opt->ts_needtime) {
 			struct timeval tv;
-			__u32 midtime;
+			__be32 midtime;
 			do_gettimeofday(&tv);
 			midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
 			memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
@@ -91,7 +91,7 @@
 	unsigned char *sptr, *dptr;
 	int soffset, doffset;
 	int	optlen;
-	u32	daddr;
+	__be32	daddr;
 
 	memset(dopt, 0, sizeof(struct ip_options));
 
@@ -148,7 +148,7 @@
 					dopt->ts_needtime = 0;
 
 					if (soffset + 8 <= optlen) {
-						__u32 addr;
+						__be32 addr;
 
 						memcpy(&addr, sptr+soffset-1, 4);
 						if (inet_addr_type(addr) != RTN_LOCAL) {
@@ -165,7 +165,7 @@
 	}
 	if (sopt->srr) {
 		unsigned char * start = sptr+sopt->srr;
-		u32 faddr;
+		__be32 faddr;
 
 		optlen  = start[1];
 		soffset = start[2];
@@ -362,7 +362,7 @@
 				goto error;
 			}
 			if (optptr[2] <= optlen) {
-				__u32 * timeptr = NULL;
+				__be32 *timeptr = NULL;
 				if (optptr[2]+3 > optptr[1]) {
 					pp_ptr = optptr + 2;
 					goto error;
@@ -371,7 +371,7 @@
 				      case IPOPT_TS_TSONLY:
 					opt->ts = optptr - iph;
 					if (skb) 
-						timeptr = (__u32*)&optptr[optptr[2]-1];
+						timeptr = (__be32*)&optptr[optptr[2]-1];
 					opt->ts_needtime = 1;
 					optptr[2] += 4;
 					break;
@@ -383,7 +383,7 @@
 					opt->ts = optptr - iph;
 					if (skb) {
 						memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
-						timeptr = (__u32*)&optptr[optptr[2]+3];
+						timeptr = (__be32*)&optptr[optptr[2]+3];
 					}
 					opt->ts_needaddr = 1;
 					opt->ts_needtime = 1;
@@ -396,12 +396,12 @@
 					}
 					opt->ts = optptr - iph;
 					{
-						u32 addr;
+						__be32 addr;
 						memcpy(&addr, &optptr[optptr[2]-1], 4);
 						if (inet_addr_type(addr) == RTN_UNICAST)
 							break;
 						if (skb)
-							timeptr = (__u32*)&optptr[optptr[2]+3];
+							timeptr = (__be32*)&optptr[optptr[2]+3];
 					}
 					opt->ts_needtime = 1;
 					optptr[2] += 8;
@@ -415,10 +415,10 @@
 				}
 				if (timeptr) {
 					struct timeval tv;
-					__u32  midtime;
+					__be32  midtime;
 					do_gettimeofday(&tv);
 					midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
-					memcpy(timeptr, &midtime, sizeof(__u32));
+					memcpy(timeptr, &midtime, sizeof(__be32));
 					opt->is_changed = 1;
 				}
 			} else {
@@ -607,7 +607,7 @@
 {
 	struct ip_options *opt = &(IPCB(skb)->opt);
 	int srrspace, srrptr;
-	u32 nexthop;
+	__be32 nexthop;
 	struct iphdr *iph = skb->nh.iph;
 	unsigned char * optptr = skb->nh.raw + opt->srr;
 	struct rtable *rt = (struct rtable*)skb->dst;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 97aee76..fc195a4 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -118,7 +118,7 @@
  *
  */
 int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
-			  u32 saddr, u32 daddr, struct ip_options *opt)
+			  __be32 saddr, __be32 daddr, struct ip_options *opt)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct rtable *rt = (struct rtable *)skb->dst;
@@ -306,7 +306,7 @@
 	/* Make sure we can route this packet. */
 	rt = (struct rtable *)__sk_dst_check(sk, 0);
 	if (rt == NULL) {
-		u32 daddr;
+		__be32 daddr;
 
 		/* Use correct destination address if we have options. */
 		daddr = inet->daddr;
@@ -1340,7 +1340,7 @@
 		char			data[40];
 	} replyopts;
 	struct ipcm_cookie ipc;
-	u32 daddr;
+	__be32 daddr;
 	struct rtable *rt = (struct rtable*)skb->dst;
 
 	if (ip_options_echo(&replyopts.opt, skb))
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 2d05c41..4b13295 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -254,7 +254,7 @@
 }
 
 void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
-		   u16 port, u32 info, u8 *payload)
+		   __be16 port, u32 info, u8 *payload)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct sock_exterr_skb *serr;
@@ -283,7 +283,7 @@
 		kfree_skb(skb);
 }
 
-void ip_local_error(struct sock *sk, int err, u32 daddr, u16 port, u32 info)
+void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct sock_exterr_skb *serr;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 1734243..2017d36 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -183,7 +183,7 @@
 
 static void ipcomp4_err(struct sk_buff *skb, u32 info)
 {
-	u32 spi;
+	__be32 spi;
 	struct iphdr *iph = (struct iphdr *)skb->data;
 	struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
 	struct xfrm_state *x;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ba49588..97cfa97 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -462,7 +462,7 @@
 	return 0;
 }
 
-static struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp)
+static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp)
 {
 	int line=MFC_HASH(mcastgrp,origin);
 	struct mfc_cache *c;
@@ -1097,7 +1097,7 @@
  *	important for multicast video.
  */
  
-static void ip_encap(struct sk_buff *skb, u32 saddr, u32 daddr)
+static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
 {
 	struct iphdr *iph = (struct iphdr *)skb_push(skb,sizeof(struct iphdr));
 
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 87b8381..8832eb5 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -115,9 +115,9 @@
 /*
  *	Returns hash value for IPVS connection entry
  */
-static unsigned int ip_vs_conn_hashkey(unsigned proto, __u32 addr, __u16 port)
+static unsigned int ip_vs_conn_hashkey(unsigned proto, __be32 addr, __be16 port)
 {
-	return jhash_3words(addr, port, proto, ip_vs_conn_rnd)
+	return jhash_3words((__force u32)addr, (__force u32)port, proto, ip_vs_conn_rnd)
 		& IP_VS_CONN_TAB_MASK;
 }
 
@@ -188,7 +188,7 @@
  *	d_addr, d_port: pkt dest address (load balancer)
  */
 static inline struct ip_vs_conn *__ip_vs_conn_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp;
@@ -215,7 +215,7 @@
 }
 
 struct ip_vs_conn *ip_vs_conn_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
 	struct ip_vs_conn *cp;
 
@@ -234,7 +234,7 @@
 
 /* Get reference to connection template */
 struct ip_vs_conn *ip_vs_ct_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp;
@@ -274,7 +274,7 @@
  *	d_addr, d_port: pkt dest address (foreign host)
  */
 struct ip_vs_conn *ip_vs_conn_out_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp, *ret=NULL;
@@ -324,7 +324,7 @@
 /*
  *	Fill a no_client_port connection with a client port number
  */
-void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __u16 cport)
+void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport)
 {
 	if (ip_vs_conn_unhash(cp)) {
 		spin_lock(&cp->lock);
@@ -508,10 +508,10 @@
 		/*
 		 * Invalidate the connection template
 		 */
-		if (ct->vport != 65535) {
+		if (ct->vport != htons(0xffff)) {
 			if (ip_vs_conn_unhash(ct)) {
-				ct->dport = 65535;
-				ct->vport = 65535;
+				ct->dport = htons(0xffff);
+				ct->vport = htons(0xffff);
 				ct->cport = 0;
 				ip_vs_conn_hash(ct);
 			}
@@ -596,8 +596,8 @@
  *	Create a new connection entry and hash it into the ip_vs_conn_tab
  */
 struct ip_vs_conn *
-ip_vs_conn_new(int proto, __u32 caddr, __u16 cport, __u32 vaddr, __u16 vport,
-	       __u32 daddr, __u16 dport, unsigned flags,
+ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport,
+	       __be32 daddr, __be16 dport, unsigned flags,
 	       struct ip_vs_dest *dest)
 {
 	struct ip_vs_conn *cp;
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 3f47ad8..6dee039 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -209,14 +209,14 @@
 static struct ip_vs_conn *
 ip_vs_sched_persist(struct ip_vs_service *svc,
 		    const struct sk_buff *skb,
-		    __u16 ports[2])
+		    __be16 ports[2])
 {
 	struct ip_vs_conn *cp = NULL;
 	struct iphdr *iph = skb->nh.iph;
 	struct ip_vs_dest *dest;
 	struct ip_vs_conn *ct;
-	__u16  dport;	 /* destination port to forward */
-	__u32  snet;	 /* source network of the client, after masking */
+	__be16  dport;	 /* destination port to forward */
+	__be32  snet;	 /* source network of the client, after masking */
 
 	/* Mask saddr with the netmask to adjust template granularity */
 	snet = iph->saddr & svc->netmask;
@@ -383,7 +383,7 @@
 	struct ip_vs_conn *cp = NULL;
 	struct iphdr *iph = skb->nh.iph;
 	struct ip_vs_dest *dest;
-	__u16 _ports[2], *pptr;
+	__be16 _ports[2], *pptr;
 
 	pptr = skb_header_pointer(skb, iph->ihl*4,
 				  sizeof(_ports), _ports);
@@ -446,7 +446,7 @@
 int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 		struct ip_vs_protocol *pp)
 {
-	__u16 _ports[2], *pptr;
+	__be16 _ports[2], *pptr;
 	struct iphdr *iph = skb->nh.iph;
 
 	pptr = skb_header_pointer(skb, iph->ihl*4,
@@ -576,7 +576,7 @@
 
 	/* the TCP/UDP port */
 	if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol) {
-		__u16 *ports = (void *)ciph + ciph->ihl*4;
+		__be16 *ports = (void *)ciph + ciph->ihl*4;
 
 		if (inout)
 			ports[1] = cp->vport;
@@ -775,7 +775,7 @@
 		if (sysctl_ip_vs_nat_icmp_send &&
 		    (pp->protocol == IPPROTO_TCP ||
 		     pp->protocol == IPPROTO_UDP)) {
-			__u16 _ports[2], *pptr;
+			__be16 _ports[2], *pptr;
 
 			pptr = skb_header_pointer(skb, ihl,
 						  sizeof(_ports), _ports);
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 6a28faf..f261616 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -283,7 +283,7 @@
  *	Returns hash value for virtual service
  */
 static __inline__ unsigned
-ip_vs_svc_hashkey(unsigned proto, __u32 addr, __u16 port)
+ip_vs_svc_hashkey(unsigned proto, __be32 addr, __be16 port)
 {
 	register unsigned porth = ntohs(port);
 
@@ -365,7 +365,7 @@
  *	Get service by {proto,addr,port} in the service table.
  */
 static __inline__ struct ip_vs_service *
-__ip_vs_service_get(__u16 protocol, __u32 vaddr, __u16 vport)
+__ip_vs_service_get(__u16 protocol, __be32 vaddr, __be16 vport)
 {
 	unsigned hash;
 	struct ip_vs_service *svc;
@@ -410,7 +410,7 @@
 }
 
 struct ip_vs_service *
-ip_vs_service_get(__u32 fwmark, __u16 protocol, __u32 vaddr, __u16 vport)
+ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
 {
 	struct ip_vs_service *svc;
 
@@ -480,7 +480,7 @@
 /*
  *	Returns hash value for real service
  */
-static __inline__ unsigned ip_vs_rs_hashkey(__u32 addr, __u16 port)
+static __inline__ unsigned ip_vs_rs_hashkey(__be32 addr, __be16 port)
 {
 	register unsigned porth = ntohs(port);
 
@@ -531,7 +531,7 @@
  *	Lookup real service by <proto,addr,port> in the real service table.
  */
 struct ip_vs_dest *
-ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport)
+ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport)
 {
 	unsigned hash;
 	struct ip_vs_dest *dest;
@@ -562,7 +562,7 @@
  *	Lookup destination by {addr,port} in the given service
  */
 static struct ip_vs_dest *
-ip_vs_lookup_dest(struct ip_vs_service *svc, __u32 daddr, __u16 dport)
+ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
 {
 	struct ip_vs_dest *dest;
 
@@ -591,7 +591,7 @@
  *  scheduling.
  */
 static struct ip_vs_dest *
-ip_vs_trash_get_dest(struct ip_vs_service *svc, __u32 daddr, __u16 dport)
+ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
 {
 	struct ip_vs_dest *dest, *nxt;
 
@@ -773,8 +773,8 @@
 ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
 {
 	struct ip_vs_dest *dest;
-	__u32 daddr = udest->addr;
-	__u16 dport = udest->port;
+	__be32 daddr = udest->addr;
+	__be16 dport = udest->port;
 	int ret;
 
 	EnterFunction(2);
@@ -879,8 +879,8 @@
 ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
 {
 	struct ip_vs_dest *dest;
-	__u32 daddr = udest->addr;
-	__u16 dport = udest->port;
+	__be32 daddr = udest->addr;
+	__be16 dport = udest->port;
 
 	EnterFunction(2);
 
@@ -991,8 +991,8 @@
 ip_vs_del_dest(struct ip_vs_service *svc,struct ip_vs_dest_user *udest)
 {
 	struct ip_vs_dest *dest;
-	__u32 daddr = udest->addr;
-	__u16 dport = udest->port;
+	__be32 daddr = udest->addr;
+	__be16 dport = udest->port;
 
 	EnterFunction(2);
 
diff --git a/net/ipv4/ipvs/ip_vs_dh.c b/net/ipv4/ipvs/ip_vs_dh.c
index 9fee19c..502111f 100644
--- a/net/ipv4/ipvs/ip_vs_dh.c
+++ b/net/ipv4/ipvs/ip_vs_dh.c
@@ -66,7 +66,7 @@
 /*
  *	Returns hash value for IPVS DH entry
  */
-static inline unsigned ip_vs_dh_hashkey(__u32 addr)
+static inline unsigned ip_vs_dh_hashkey(__be32 addr)
 {
 	return (ntohl(addr)*2654435761UL) & IP_VS_DH_TAB_MASK;
 }
@@ -76,7 +76,7 @@
  *      Get ip_vs_dest associated with supplied parameters.
  */
 static inline struct ip_vs_dest *
-ip_vs_dh_get(struct ip_vs_dh_bucket *tbl, __u32 addr)
+ip_vs_dh_get(struct ip_vs_dh_bucket *tbl, __be32 addr)
 {
 	return (tbl[ip_vs_dh_hashkey(addr)]).dest;
 }
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c
index 37fafb1..e433cb0 100644
--- a/net/ipv4/ipvs/ip_vs_ftp.c
+++ b/net/ipv4/ipvs/ip_vs_ftp.c
@@ -32,6 +32,7 @@
 #include <linux/ip.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
+#include <asm/unaligned.h>
 
 #include <net/ip_vs.h>
 
@@ -44,8 +45,8 @@
  * List of ports (up to IP_VS_APP_MAX_PORTS) to be handled by helper
  * First port is set to the default port.
  */
-static int ports[IP_VS_APP_MAX_PORTS] = {21, 0};
-module_param_array(ports, int, NULL, 0);
+static unsigned short ports[IP_VS_APP_MAX_PORTS] = {21, 0};
+module_param_array(ports, ushort, NULL, 0);
 MODULE_PARM_DESC(ports, "Ports to monitor for FTP control commands");
 
 
@@ -74,7 +75,7 @@
  */
 static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
 				  const char *pattern, size_t plen, char term,
-				  __u32 *addr, __u16 *port,
+				  __be32 *addr, __be16 *port,
 				  char **start, char **end)
 {
 	unsigned char p[6];
@@ -114,8 +115,8 @@
 	if (i != 5)
 		return -1;
 
-	*addr = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
-	*port = (p[5]<<8) | p[4];
+	*addr = get_unaligned((__be32 *)p);
+	*port = get_unaligned((__be16 *)(p + 4));
 	return 1;
 }
 
@@ -140,8 +141,8 @@
 	struct tcphdr *th;
 	char *data, *data_limit;
 	char *start, *end;
-	__u32 from;
-	__u16 port;
+	__be32 from;
+	__be16 port;
 	struct ip_vs_conn *n_cp;
 	char buf[24];		/* xxx.xxx.xxx.xxx,ppp,ppp\000 */
 	unsigned buf_len;
@@ -199,7 +200,7 @@
 		from = n_cp->vaddr;
 		port = n_cp->vport;
 		sprintf(buf,"%d,%d,%d,%d,%d,%d", NIPQUAD(from),
-			port&255, (port>>8)&255);
+			ntohs(port)&255, (ntohs(port)>>8)&255);
 		buf_len = strlen(buf);
 
 		/*
@@ -243,8 +244,8 @@
 	struct tcphdr *th;
 	char *data, *data_start, *data_limit;
 	char *start, *end;
-	__u32 to;
-	__u16 port;
+	__be32 to;
+	__be16 port;
 	struct ip_vs_conn *n_cp;
 
 	/* no diff required for incoming packets */
@@ -365,12 +366,6 @@
 	for (i=0; i<IP_VS_APP_MAX_PORTS; i++) {
 		if (!ports[i])
 			continue;
-		if (ports[i] < 0 || ports[i] > 0xffff) {
-			IP_VS_WARNING("ip_vs_ftp: Ignoring invalid "
-				      "configuration port[%d] = %d\n",
-				      i, ports[i]);
-			continue;
-		}
 		ret = register_ip_vs_app_inc(app, app->protocol, ports[i]);
 		if (ret)
 			break;
diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c
index 6e5cb92..524751e 100644
--- a/net/ipv4/ipvs/ip_vs_lblc.c
+++ b/net/ipv4/ipvs/ip_vs_lblc.c
@@ -87,7 +87,7 @@
  */
 struct ip_vs_lblc_entry {
 	struct list_head        list;
-	__u32                   addr;           /* destination IP address */
+	__be32                  addr;           /* destination IP address */
 	struct ip_vs_dest       *dest;          /* real server (cache) */
 	unsigned long           lastuse;        /* last used time */
 };
@@ -160,7 +160,7 @@
  *      IP address to a server.
  */
 static inline struct ip_vs_lblc_entry *
-ip_vs_lblc_new(__u32 daddr, struct ip_vs_dest *dest)
+ip_vs_lblc_new(__be32 daddr, struct ip_vs_dest *dest)
 {
 	struct ip_vs_lblc_entry *en;
 
@@ -195,7 +195,7 @@
 /*
  *	Returns hash value for IPVS LBLC entry
  */
-static inline unsigned ip_vs_lblc_hashkey(__u32 addr)
+static inline unsigned ip_vs_lblc_hashkey(__be32 addr)
 {
 	return (ntohl(addr)*2654435761UL) & IP_VS_LBLC_TAB_MASK;
 }
@@ -234,7 +234,7 @@
  *  Get ip_vs_lblc_entry associated with supplied parameters.
  */
 static inline struct ip_vs_lblc_entry *
-ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __u32 addr)
+ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __be32 addr)
 {
 	unsigned hash;
 	struct ip_vs_lblc_entry *en;
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c
index 32ba37b..0899019 100644
--- a/net/ipv4/ipvs/ip_vs_lblcr.c
+++ b/net/ipv4/ipvs/ip_vs_lblcr.c
@@ -276,7 +276,7 @@
  */
 struct ip_vs_lblcr_entry {
 	struct list_head        list;
-	__u32                   addr;           /* destination IP address */
+	__be32                   addr;           /* destination IP address */
 	struct ip_vs_dest_set   set;            /* destination server set */
 	unsigned long           lastuse;        /* last used time */
 };
@@ -348,7 +348,7 @@
  *      new/free a ip_vs_lblcr_entry, which is a mapping of a destination
  *      IP address to a server.
  */
-static inline struct ip_vs_lblcr_entry *ip_vs_lblcr_new(__u32 daddr)
+static inline struct ip_vs_lblcr_entry *ip_vs_lblcr_new(__be32 daddr)
 {
 	struct ip_vs_lblcr_entry *en;
 
@@ -381,7 +381,7 @@
 /*
  *	Returns hash value for IPVS LBLCR entry
  */
-static inline unsigned ip_vs_lblcr_hashkey(__u32 addr)
+static inline unsigned ip_vs_lblcr_hashkey(__be32 addr)
 {
 	return (ntohl(addr)*2654435761UL) & IP_VS_LBLCR_TAB_MASK;
 }
@@ -420,7 +420,7 @@
  *  Get ip_vs_lblcr_entry associated with supplied parameters.
  */
 static inline struct ip_vs_lblcr_entry *
-ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __u32 addr)
+ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __be32 addr)
 {
 	unsigned hash;
 	struct ip_vs_lblcr_entry *en;
diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c
index 867d4e9..c4528b5 100644
--- a/net/ipv4/ipvs/ip_vs_proto.c
+++ b/net/ipv4/ipvs/ip_vs_proto.c
@@ -176,7 +176,7 @@
 			pp->name, NIPQUAD(ih->saddr),
 			NIPQUAD(ih->daddr));
 	else {
-		__u16 _ports[2], *pptr
+		__be16 _ports[2], *pptr
 ;
 		pptr = skb_header_pointer(skb, offset + ih->ihl*4,
 					  sizeof(_ports), _ports);
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index 820e831..bfe779e 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -29,7 +29,7 @@
 tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-	__u16 _ports[2], *pptr;
+	__be16 _ports[2], *pptr;
 
 	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
 	if (pptr == NULL)
@@ -50,7 +50,7 @@
 tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-	__u16 _ports[2], *pptr;
+	__be16 _ports[2], *pptr;
 
 	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
 	if (pptr == NULL)
@@ -112,12 +112,12 @@
 
 
 static inline void
-tcp_fast_csum_update(struct tcphdr *tcph, u32 oldip, u32 newip,
-		     u16 oldport, u16 newport)
+tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip,
+		     __be16 oldport, __be16 newport)
 {
 	tcph->check =
 		ip_vs_check_diff(~oldip, newip,
-				 ip_vs_check_diff(oldport ^ 0xFFFF,
+				 ip_vs_check_diff(oldport ^ htonl(0xFFFF),
 						  newport, tcph->check));
 }
 
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 90c8166..54aa760 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -29,7 +29,7 @@
 		const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
 	struct ip_vs_conn *cp;
-	__u16 _ports[2], *pptr;
+	__be16 _ports[2], *pptr;
 
 	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
 	if (pptr == NULL)
@@ -54,7 +54,7 @@
 		 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
 	struct ip_vs_conn *cp;
-	__u16 _ports[2], *pptr;
+	__be16 _ports[2], *pptr;
 
 	pptr = skb_header_pointer(skb, skb->nh.iph->ihl*4,
 				  sizeof(_ports), _ports);
@@ -117,15 +117,15 @@
 
 
 static inline void
-udp_fast_csum_update(struct udphdr *uhdr, u32 oldip, u32 newip,
-		     u16 oldport, u16 newport)
+udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip,
+		     __be16 oldport, __be16 newport)
 {
 	uhdr->check =
 		ip_vs_check_diff(~oldip, newip,
-				 ip_vs_check_diff(oldport ^ 0xFFFF,
+				 ip_vs_check_diff(oldport ^ htonl(0xFFFF),
 						  newport, uhdr->check));
 	if (!uhdr->check)
-		uhdr->check = 0xFFFF;
+		uhdr->check = htonl(0xFFFF);
 }
 
 static int
@@ -173,7 +173,7 @@
 						cp->protocol,
 						(*pskb)->csum);
 		if (udph->check == 0)
-			udph->check = 0xFFFF;
+			udph->check = htonl(0xFFFF);
 		IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
 			  pp->name, udph->check,
 			  (char*)&(udph->check) - (char*)udph);
diff --git a/net/ipv4/ipvs/ip_vs_sh.c b/net/ipv4/ipvs/ip_vs_sh.c
index 7775e6c..338668f 100644
--- a/net/ipv4/ipvs/ip_vs_sh.c
+++ b/net/ipv4/ipvs/ip_vs_sh.c
@@ -63,7 +63,7 @@
 /*
  *	Returns hash value for IPVS SH entry
  */
-static inline unsigned ip_vs_sh_hashkey(__u32 addr)
+static inline unsigned ip_vs_sh_hashkey(__be32 addr)
 {
 	return (ntohl(addr)*2654435761UL) & IP_VS_SH_TAB_MASK;
 }
@@ -73,7 +73,7 @@
  *      Get ip_vs_dest associated with supplied parameters.
  */
 static inline struct ip_vs_dest *
-ip_vs_sh_get(struct ip_vs_sh_bucket *tbl, __u32 addr)
+ip_vs_sh_get(struct ip_vs_sh_bucket *tbl, __be32 addr)
 {
 	return (tbl[ip_vs_sh_hashkey(addr)]).dest;
 }
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 1bca714..6ab57d7 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -48,16 +48,16 @@
 
 	/* Protocol, addresses and port numbers */
 	__u8			protocol;       /* Which protocol (TCP/UDP) */
-	__u16			cport;
-	__u16                   vport;
-	__u16                   dport;
-	__u32                   caddr;          /* client address */
-	__u32                   vaddr;          /* virtual address */
-	__u32                   daddr;          /* destination address */
+	__be16			cport;
+	__be16                  vport;
+	__be16                  dport;
+	__be32                  caddr;          /* client address */
+	__be32                  vaddr;          /* virtual address */
+	__be32                  daddr;          /* destination address */
 
 	/* Flags and state transition */
-	__u16                   flags;          /* status flags */
-	__u16                   state;          /* state info */
+	__be16                  flags;          /* status flags */
+	__be16                  state;          /* state info */
 
 	/* The sequence options start here */
 };
@@ -464,7 +464,7 @@
 static int bind_mcastif_addr(struct socket *sock, char *ifname)
 {
 	struct net_device *dev;
-	u32 addr;
+	__be32 addr;
 	struct sockaddr_in sin;
 
 	if ((dev = __dev_get_by_name(ifname)) == NULL)
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 52c12e9..e1f77bd 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -232,7 +232,7 @@
 
 	/* check if it is a connection of no-client-port */
 	if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
-		__u16 _pt, *p;
+		__be16 _pt, *p;
 		p = skb_header_pointer(skb, iph->ihl*4, sizeof(_pt), &_pt);
 		if (p == NULL)
 			goto tx_error;
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
index d25ec4a..92b0482 100644
--- a/net/ipv4/multipath_wrandom.c
+++ b/net/ipv4/multipath_wrandom.c
@@ -60,8 +60,8 @@
 	struct list_head	list;
 
 	const struct fib_nh	*nh_info;
-	__u32			netmask;
-	__u32			network;
+	__be32			netmask;
+	__be32			network;
 	unsigned char		prefixlen;
 
 	struct rcu_head		rcu;
@@ -76,7 +76,7 @@
 	struct list_head	list;
 
 	int			oif;
-	__u32			gw;
+	__be32			gw;
 	struct list_head	dests;
 
 	struct rcu_head		rcu;
@@ -128,8 +128,8 @@
 
 	/* find state entry for destination */
 	list_for_each_entry_rcu(d, &target_route->dests, list) {
-		__u32 targetnetwork = fl->fl4_dst & 
-			(0xFFFFFFFF >> (32 - d->prefixlen));
+		__be32 targetnetwork = fl->fl4_dst &
+			inet_make_mask(d->prefixlen);
 
 		if ((targetnetwork & d->netmask) == d->network) {
 			weight = d->nh_info->nh_weight;
@@ -217,8 +217,8 @@
 	*rp = decision;
 }
 
-static void wrandom_set_nhinfo(__u32 network,
-			       __u32 netmask,
+static void wrandom_set_nhinfo(__be32 network,
+			       __be32 netmask,
 			       unsigned char prefixlen,
 			       const struct fib_nh *nh)
 {
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index f88347d..5ac1537 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -128,8 +128,8 @@
  */
 
 struct ip_rt_info {
-	u_int32_t daddr;
-	u_int32_t saddr;
+	__be32 daddr;
+	__be32 saddr;
 	u_int8_t tos;
 };
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 85f0d73..17e1a68 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -80,7 +80,7 @@
 {
 	char *arpptr = (char *)(arphdr + 1);
 	char *src_devaddr, *tgt_devaddr;
-	u32 src_ipaddr, tgt_ipaddr;
+	__be32 src_ipaddr, tgt_ipaddr;
 	int i, ret;
 
 #define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg))
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 0a7bd7f..6c7383a 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -155,11 +155,11 @@
 		exp->tuple.dst.protonum = IPPROTO_TCP;
 		exp->tuple.dst.u.tcp.port = htons(port);
 
-		exp->mask.src.ip = 0xFFFFFFFF;
+		exp->mask.src.ip = htonl(0xFFFFFFFF);
 		exp->mask.src.u.tcp.port = 0;
-		exp->mask.dst.ip = 0xFFFFFFFF;
+		exp->mask.dst.ip = htonl(0xFFFFFFFF);
 		exp->mask.dst.protonum = 0xFF;
-		exp->mask.dst.u.tcp.port = 0xFFFF;
+		exp->mask.dst.u.tcp.port = htons(0xFFFF);
 
 		if (ip_nat_amanda_hook)
 			ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index c432b31..143c466 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -149,8 +149,8 @@
 static u_int32_t __hash_conntrack(const struct ip_conntrack_tuple *tuple,
 			    unsigned int size, unsigned int rnd)
 {
-	return (jhash_3words(tuple->src.ip,
-	                     (tuple->dst.ip ^ tuple->dst.protonum),
+	return (jhash_3words((__force u32)tuple->src.ip,
+	                     ((__force u32)tuple->dst.ip ^ tuple->dst.protonum),
 	                     (tuple->src.u.all | (tuple->dst.u.all << 16)),
 	                     rnd) % size);
 }
@@ -1169,9 +1169,9 @@
 int ip_ct_port_tuple_to_nfattr(struct sk_buff *skb,
 			       const struct ip_conntrack_tuple *tuple)
 {
-	NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(u_int16_t),
+	NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(__be16),
 		&tuple->src.u.tcp.port);
-	NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(u_int16_t),
+	NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(__be16),
 		&tuple->dst.u.tcp.port);
 	return 0;
 
@@ -1186,9 +1186,9 @@
 		return -EINVAL;
 
 	t->src.u.tcp.port =
-		*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
+		*(__be16 *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
 	t->dst.u.tcp.port =
-		*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
+		*(__be16 *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
 
 	return 0;
 }
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 1d18c86..93dcf96 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -425,8 +425,8 @@
 	exp->tuple.src.u.tcp.port = 0; /* Don't care. */
 	exp->tuple.dst.protonum = IPPROTO_TCP;
 	exp->mask = ((struct ip_conntrack_tuple)
-		{ { 0xFFFFFFFF, { 0 } },
-		  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+		{ { htonl(0xFFFFFFFF), { 0 } },
+		  { htonl(0xFFFFFFFF), { .tcp = { htons(0xFFFF) } }, 0xFF }});
 
 	exp->expectfn = NULL;
 	exp->flags = 0;
@@ -488,7 +488,7 @@
 	for (i = 0; i < ports_c; i++) {
 		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
 		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
-		ftp[i].mask.src.u.tcp.port = 0xFFFF;
+		ftp[i].mask.src.u.tcp.port = htons(0xFFFF);
 		ftp[i].mask.dst.protonum = 0xFF;
 		ftp[i].max_expected = 1;
 		ftp[i].timeout = 5 * 60; /* 5 minutes */
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index 9a39e29..7b74412 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -49,11 +49,11 @@
 int (*set_h245_addr_hook) (struct sk_buff ** pskb,
 			   unsigned char **data, int dataoff,
 			   H245_TransportAddress * addr,
-			   u_int32_t ip, u_int16_t port);
+			   __be32 ip, u_int16_t port);
 int (*set_h225_addr_hook) (struct sk_buff ** pskb,
 			   unsigned char **data, int dataoff,
 			   TransportAddress * addr,
-			   u_int32_t ip, u_int16_t port);
+			   __be32 ip, u_int16_t port);
 int (*set_sig_addr_hook) (struct sk_buff ** pskb,
 			  struct ip_conntrack * ct,
 			  enum ip_conntrack_info ctinfo,
@@ -209,7 +209,7 @@
 
 /****************************************************************************/
 static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
-			 u_int32_t * ip, u_int16_t * port)
+			 __be32 * ip, u_int16_t * port)
 {
 	unsigned char *p;
 
@@ -232,7 +232,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	u_int16_t rtp_port;
 	struct ip_conntrack_expect *rtp_exp;
@@ -254,10 +254,10 @@
 	rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
 	rtp_exp->tuple.dst.u.udp.port = htons(rtp_port);
 	rtp_exp->tuple.dst.protonum = IPPROTO_UDP;
-	rtp_exp->mask.src.ip = 0xFFFFFFFF;
+	rtp_exp->mask.src.ip = htonl(0xFFFFFFFF);
 	rtp_exp->mask.src.u.udp.port = 0;
-	rtp_exp->mask.dst.ip = 0xFFFFFFFF;
-	rtp_exp->mask.dst.u.udp.port = 0xFFFF;
+	rtp_exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	rtp_exp->mask.dst.u.udp.port = htons(0xFFFF);
 	rtp_exp->mask.dst.protonum = 0xFF;
 	rtp_exp->flags = 0;
 
@@ -271,10 +271,10 @@
 	rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
 	rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1);
 	rtcp_exp->tuple.dst.protonum = IPPROTO_UDP;
-	rtcp_exp->mask.src.ip = 0xFFFFFFFF;
+	rtcp_exp->mask.src.ip = htonl(0xFFFFFFFF);
 	rtcp_exp->mask.src.u.udp.port = 0;
-	rtcp_exp->mask.dst.ip = 0xFFFFFFFF;
-	rtcp_exp->mask.dst.u.udp.port = 0xFFFF;
+	rtcp_exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	rtcp_exp->mask.dst.u.udp.port = htons(0xFFFF);
 	rtcp_exp->mask.dst.protonum = 0xFF;
 	rtcp_exp->flags = 0;
 
@@ -325,7 +325,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp = NULL;
 
@@ -342,10 +342,10 @@
 	exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
 	exp->tuple.dst.u.tcp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_TCP;
-	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.ip = htonl(0xFFFFFFFF);
 	exp->mask.src.u.tcp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.tcp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = IP_CT_EXPECT_PERMANENT;	/* Accept multiple channels */
 
@@ -626,7 +626,7 @@
 
 /****************************************************************************/
 int get_h225_addr(unsigned char *data, TransportAddress * addr,
-		  u_int32_t * ip, u_int16_t * port)
+		  __be32 * ip, u_int16_t * port)
 {
 	unsigned char *p;
 
@@ -648,7 +648,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp = NULL;
 
@@ -665,10 +665,10 @@
 	exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
 	exp->tuple.dst.u.tcp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_TCP;
-	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.ip = htonl(0xFFFFFFFF);
 	exp->mask.src.u.tcp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.tcp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = 0;
 
@@ -709,7 +709,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp = NULL;
 
@@ -751,10 +751,10 @@
 	exp->tuple.dst.ip = ip;
 	exp->tuple.dst.u.tcp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_TCP;
-	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.ip = htonl(0xFFFFFFFF);
 	exp->mask.src.u.tcp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.tcp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = 0;
 
@@ -791,7 +791,7 @@
 	int dir = CTINFO2DIR(ctinfo);
 	int ret;
 	int i;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 
 	DEBUGP("ip_ct_q931: Setup\n");
@@ -1188,7 +1188,7 @@
 
 /****************************************************************************/
 static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct,
-					       u_int32_t ip, u_int16_t port)
+					       __be32 ip, u_int16_t port)
 {
 	struct ip_conntrack_expect *exp;
 	struct ip_conntrack_tuple tuple;
@@ -1228,7 +1228,7 @@
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
 	int i;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp;
 
@@ -1251,10 +1251,10 @@
 	exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
 	exp->tuple.dst.u.tcp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_TCP;
-	exp->mask.src.ip = gkrouted_only ? 0xFFFFFFFF : 0;
+	exp->mask.src.ip = gkrouted_only ? htonl(0xFFFFFFFF) : 0;
 	exp->mask.src.u.tcp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.tcp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = IP_CT_EXPECT_PERMANENT;	/* Accept multiple calls */
 
@@ -1307,7 +1307,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp;
 
@@ -1333,10 +1333,10 @@
 	exp->tuple.dst.ip = ip;
 	exp->tuple.dst.u.tcp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_UDP;
-	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.ip = htonl(0xFFFFFFFF);
 	exp->mask.src.u.tcp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.tcp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = 0;
 	exp->expectfn = ip_conntrack_ras_expect;
@@ -1477,7 +1477,7 @@
 {
 	struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
 	int dir = CTINFO2DIR(ctinfo);
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 
 	DEBUGP("ip_ct_ras: ARQ\n");
@@ -1513,7 +1513,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp;
 
@@ -1538,10 +1538,10 @@
 	exp->tuple.dst.ip = ip;
 	exp->tuple.dst.u.tcp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_TCP;
-	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.ip = htonl(0xFFFFFFFF);
 	exp->mask.src.u.tcp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.tcp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = IP_CT_EXPECT_PERMANENT;
 	exp->expectfn = ip_conntrack_q931_expect;
@@ -1581,7 +1581,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int ret = 0;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 	struct ip_conntrack_expect *exp = NULL;
 
@@ -1598,10 +1598,10 @@
 	exp->tuple.dst.ip = ip;
 	exp->tuple.dst.u.tcp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_TCP;
-	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.ip = htonl(0xFFFFFFFF);
 	exp->mask.src.u.tcp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.tcp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 	exp->flags = IP_CT_EXPECT_PERMANENT;
 	exp->expectfn = ip_conntrack_q931_expect;
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index fb0aee6..a2af5e0 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -242,10 +242,10 @@
 	exp_orig->tuple.dst.u.gre.key = callid;
 	exp_orig->tuple.dst.protonum = IPPROTO_GRE;
 
-	exp_orig->mask.src.ip = 0xffffffff;
+	exp_orig->mask.src.ip = htonl(0xffffffff);
 	exp_orig->mask.src.u.all = 0;
 	exp_orig->mask.dst.u.gre.key = htons(0xffff);
-	exp_orig->mask.dst.ip = 0xffffffff;
+	exp_orig->mask.dst.ip = htonl(0xffffffff);
 	exp_orig->mask.dst.protonum = 0xff;
 
 	exp_orig->master = ct;
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 4488907..75f7c3db 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -218,7 +218,8 @@
 				    IPPROTO_TCP }});
 			exp->mask = ((struct ip_conntrack_tuple)
 				{ { 0, { 0 } },
-				  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+				  { htonl(0xFFFFFFFF),
+					{ .tcp = { htons(0xFFFF) } }, 0xFF }});
 			exp->expectfn = NULL;
 			exp->flags = 0;
 			if (ip_nat_irc_hook)
@@ -266,7 +267,7 @@
 		hlpr = &irc_helpers[i];
 		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
 		hlpr->tuple.dst.protonum = IPPROTO_TCP;
-		hlpr->mask.src.u.tcp.port = 0xFFFF;
+		hlpr->mask.src.u.tcp.port = htons(0xFFFF);
 		hlpr->mask.dst.protonum = 0xFF;
 		hlpr->max_expected = max_dcc_channels;
 		hlpr->timeout = dcc_timeout;
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index 3d0b438..a1d6a89 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -48,7 +48,7 @@
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct rtable *rt = (struct rtable *)(*pskb)->dst;
 	struct in_device *in_dev;
-	u_int32_t mask = 0;
+	__be32 mask = 0;
 
 	/* we're only interested in locally generated packets */
 	if ((*pskb)->sk == NULL)
@@ -78,12 +78,12 @@
 		goto out;
 
 	exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-	exp->tuple.src.u.udp.port = ntohs(NMBD_PORT);
+	exp->tuple.src.u.udp.port = htons(NMBD_PORT);
 
 	exp->mask.src.ip          = mask;
-	exp->mask.src.u.udp.port  = 0xFFFF;
-	exp->mask.dst.ip          = 0xFFFFFFFF;
-	exp->mask.dst.u.udp.port  = 0xFFFF;
+	exp->mask.src.u.udp.port  = htons(0xFFFF);
+	exp->mask.dst.ip          = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.udp.port  = htons(0xFFFF);
 	exp->mask.dst.protonum    = 0xFF;
 
 	exp->expectfn             = NULL;
@@ -115,7 +115,7 @@
 		.src = {
 			.u = {
 				.udp = {
-					.port	= 0xFFFF,
+					.port	= __constant_htons(0xFFFF),
 				}
 			}
 		},
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 52eddea..53b6dff 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -78,8 +78,8 @@
 {
 	struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
 	
-	NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
-	NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
+	NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(__be32), &tuple->src.ip);
+	NFA_PUT(skb, CTA_IP_V4_DST, sizeof(__be32), &tuple->dst.ip);
 
 	NFA_NEST_END(skb, nest_parms);
 
@@ -110,7 +110,7 @@
 static inline int
 ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-	u_int32_t status = htonl((u_int32_t) ct->status);
+	__be32 status = htonl((u_int32_t) ct->status);
 	NFA_PUT(skb, CTA_STATUS, sizeof(status), &status);
 	return 0;
 
@@ -122,7 +122,7 @@
 ctnetlink_dump_timeout(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
 	long timeout_l = ct->timeout.expires - jiffies;
-	u_int32_t timeout;
+	__be32 timeout;
 
 	if (timeout_l < 0)
 		timeout = 0;
@@ -192,13 +192,13 @@
 {
 	enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
 	struct nfattr *nest_count = NFA_NEST(skb, type);
-	u_int32_t tmp;
+	__be32 tmp;
 
 	tmp = htonl(ct->counters[dir].packets);
-	NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
+	NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(__be32), &tmp);
 
 	tmp = htonl(ct->counters[dir].bytes);
-	NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
+	NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(__be32), &tmp);
 
 	NFA_NEST_END(skb, nest_count);
 
@@ -215,9 +215,9 @@
 static inline int
 ctnetlink_dump_mark(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-	u_int32_t mark = htonl(ct->mark);
+	__be32 mark = htonl(ct->mark);
 
-	NFA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
+	NFA_PUT(skb, CTA_MARK, sizeof(__be32), &mark);
 	return 0;
 
 nfattr_failure:
@@ -230,8 +230,8 @@
 static inline int
 ctnetlink_dump_id(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-	u_int32_t id = htonl(ct->id);
-	NFA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
+	__be32 id = htonl(ct->id);
+	NFA_PUT(skb, CTA_ID, sizeof(__be32), &id);
 	return 0;
 
 nfattr_failure:
@@ -241,9 +241,9 @@
 static inline int
 ctnetlink_dump_use(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-	u_int32_t use = htonl(atomic_read(&ct->ct_general.use));
+	__be32 use = htonl(atomic_read(&ct->ct_general.use));
 	
-	NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
+	NFA_PUT(skb, CTA_USE, sizeof(__be32), &use);
 	return 0;
 
 nfattr_failure:
@@ -457,8 +457,8 @@
 }
 
 static const size_t cta_min_ip[CTA_IP_MAX] = {
-	[CTA_IP_V4_SRC-1]	= sizeof(u_int32_t),
-	[CTA_IP_V4_DST-1]	= sizeof(u_int32_t),
+	[CTA_IP_V4_SRC-1]	= sizeof(__be32),
+	[CTA_IP_V4_DST-1]	= sizeof(__be32),
 };
 
 static inline int
@@ -475,11 +475,11 @@
 
 	if (!tb[CTA_IP_V4_SRC-1])
 		return -EINVAL;
-	tuple->src.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
+	tuple->src.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
 
 	if (!tb[CTA_IP_V4_DST-1])
 		return -EINVAL;
-	tuple->dst.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
+	tuple->dst.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
 
 	DEBUGP("leaving\n");
 
@@ -602,8 +602,8 @@
 }
 
 static const size_t cta_min_nat[CTA_NAT_MAX] = {
-	[CTA_NAT_MINIP-1]       = sizeof(u_int32_t),
-	[CTA_NAT_MAXIP-1]       = sizeof(u_int32_t),
+	[CTA_NAT_MINIP-1]       = sizeof(__be32),
+	[CTA_NAT_MAXIP-1]       = sizeof(__be32),
 };
 
 static inline int
@@ -623,12 +623,12 @@
 		return -EINVAL;
 
 	if (tb[CTA_NAT_MINIP-1])
-		range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
+		range->min_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
 
 	if (!tb[CTA_NAT_MAXIP-1])
 		range->max_ip = range->min_ip;
 	else
-		range->max_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
+		range->max_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
 
 	if (range->min_ip)
 		range->flags |= IP_NAT_RANGE_MAP_IPS;
@@ -663,11 +663,11 @@
 }
 
 static const size_t cta_min[CTA_MAX] = {
-	[CTA_STATUS-1] 		= sizeof(u_int32_t),
-	[CTA_TIMEOUT-1] 	= sizeof(u_int32_t),
-	[CTA_MARK-1]		= sizeof(u_int32_t),
-	[CTA_USE-1]		= sizeof(u_int32_t),
-	[CTA_ID-1]		= sizeof(u_int32_t)
+	[CTA_STATUS-1] 		= sizeof(__be32),
+	[CTA_TIMEOUT-1] 	= sizeof(__be32),
+	[CTA_MARK-1]		= sizeof(__be32),
+	[CTA_USE-1]		= sizeof(__be32),
+	[CTA_ID-1]		= sizeof(__be32)
 };
 
 static int
@@ -706,7 +706,7 @@
 	ct = tuplehash_to_ctrack(h);
 	
 	if (cda[CTA_ID-1]) {
-		u_int32_t id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
+		u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1]));
 		if (ct->id != id) {
 			ip_conntrack_put(ct);
 			return -ENOENT;
@@ -808,7 +808,7 @@
 ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
 {
 	unsigned long d;
-	unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
+	unsigned status = ntohl(*(__be32 *)NFA_DATA(cda[CTA_STATUS-1]));
 	d = ct->status ^ status;
 
 	if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
@@ -903,7 +903,7 @@
 static inline int
 ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[])
 {
-	u_int32_t timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+	u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
 	
 	if (!del_timer(&ct->timeout))
 		return -ETIME;
@@ -966,7 +966,7 @@
 
 #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK-1])
-		ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+		ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
 	DEBUGP("all done\n");
@@ -989,7 +989,7 @@
 
 	if (!cda[CTA_TIMEOUT-1])
 		goto err;
-	ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+	ct->timeout.expires = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
 
 	ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
 	ct->status |= IPS_CONFIRMED;
@@ -1006,7 +1006,7 @@
 
 #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK-1])
-		ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+		ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
 	ct->helper = ip_conntrack_helper_find_get(rtuple);
@@ -1138,8 +1138,8 @@
                           const struct ip_conntrack_expect *exp)
 {
 	struct ip_conntrack *master = exp->master;
-	u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ);
-	u_int32_t id = htonl(exp->id);
+	__be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
+	__be32 id = htonl(exp->id);
 
 	if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
 		goto nfattr_failure;
@@ -1150,8 +1150,8 @@
 				 CTA_EXPECT_MASTER) < 0)
 		goto nfattr_failure;
 	
-	NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
-	NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
+	NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(__be32), &timeout);
+	NFA_PUT(skb, CTA_EXPECT_ID, sizeof(__be32), &id);
 
 	return 0;
 	
@@ -1272,8 +1272,8 @@
 }
 
 static const size_t cta_min_exp[CTA_EXPECT_MAX] = {
-	[CTA_EXPECT_TIMEOUT-1]          = sizeof(u_int32_t),
-	[CTA_EXPECT_ID-1]               = sizeof(u_int32_t)
+	[CTA_EXPECT_TIMEOUT-1]          = sizeof(__be32),
+	[CTA_EXPECT_ID-1]               = sizeof(__be32)
 };
 
 static int
@@ -1321,7 +1321,7 @@
 		return -ENOENT;
 
 	if (cda[CTA_EXPECT_ID-1]) {
-		u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
+		__be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
 		if (exp->id != ntohl(id)) {
 			ip_conntrack_expect_put(exp);
 			return -ENOENT;
@@ -1375,8 +1375,8 @@
 			return -ENOENT;
 
 		if (cda[CTA_EXPECT_ID-1]) {
-			u_int32_t id = 
-				*(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
+			__be32 id =
+				*(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
 			if (exp->id != ntohl(id)) {
 				ip_conntrack_expect_put(exp);
 				return -ENOENT;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 09c40eb..295b6fa 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -261,7 +261,7 @@
 static int icmp_tuple_to_nfattr(struct sk_buff *skb,
 				const struct ip_conntrack_tuple *t)
 {
-	NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(u_int16_t),
+	NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(__be16),
 		&t->src.u.icmp.id);
 	NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t),
 		&t->dst.u.icmp.type);
@@ -287,7 +287,7 @@
 	tuple->dst.u.icmp.code =
 			*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
 	tuple->src.u.icmp.id =
-			*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+			*(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
 
 	if (tuple->dst.u.icmp.type >= sizeof(invmap)
 	    || !invmap[tuple->dst.u.icmp.type])
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index b908a48..2443322 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -210,7 +210,7 @@
 for (offset = skb->nh.iph->ihl * 4 + sizeof(sctp_sctphdr_t), count = 0;	\
 	offset < skb->len &&						\
 	(sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch));	\
-	offset += (htons(sch->length) + 3) & ~3, count++)
+	offset += (ntohs(sch->length) + 3) & ~3, count++)
 
 /* Some validity checks to make sure the chunks are fine */
 static int do_basic_checks(struct ip_conntrack *conntrack,
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 03ae9a0..06e4e8a 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -519,8 +519,8 @@
 
 	/* Fast path for timestamp-only option */
 	if (length == TCPOLEN_TSTAMP_ALIGNED*4
-	    && *(__u32 *)ptr ==
-	        __constant_ntohl((TCPOPT_NOP << 24) 
+	    && *(__be32 *)ptr ==
+	        __constant_htonl((TCPOPT_NOP << 24)
 	        		 | (TCPOPT_NOP << 16)
 	        		 | (TCPOPT_TIMESTAMP << 8)
 	        		 | TCPOLEN_TIMESTAMP))
@@ -551,7 +551,7 @@
 			    	for (i = 0;
 			    	     i < (opsize - TCPOLEN_SACK_BASE);
 			    	     i += TCPOLEN_SACK_PERBLOCK) {
-					tmp = ntohl(*((u_int32_t *)(ptr+i)+1));
+					tmp = ntohl(*((__be32 *)(ptr+i)+1));
 					
 					if (after(tmp, *sack))
 						*sack = tmp;
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index 2893e9c..f4f7599 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -193,7 +193,7 @@
 
 /* Simple ipaddr parser.. */
 static int parse_ipaddr(const char *cp,	const char **endp,
-			u_int32_t *ipaddr, const char *limit)
+			__be32 *ipaddr, const char *limit)
 {
 	unsigned long int val;
 	int i, digit = 0;
@@ -227,7 +227,7 @@
 static int epaddr_len(const char *dptr, const char *limit, int *shift)
 {
 	const char *aux = dptr;
-	u_int32_t ip;
+	__be32 ip;
 
 	if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
 		DEBUGP("ip: %s parse failed.!\n", dptr);
@@ -302,7 +302,7 @@
 static int set_expected_rtp(struct sk_buff **pskb,
 			    struct ip_conntrack *ct,
 			    enum ip_conntrack_info ctinfo,
-			    u_int32_t ipaddr, u_int16_t port,
+			    __be32 ipaddr, u_int16_t port,
 			    const char *dptr)
 {
 	struct ip_conntrack_expect *exp;
@@ -319,10 +319,10 @@
 	exp->tuple.dst.u.udp.port = htons(port);
 	exp->tuple.dst.protonum = IPPROTO_UDP;
 
-	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.ip = htonl(0xFFFFFFFF);
 	exp->mask.src.u.udp.port = 0;
-	exp->mask.dst.ip = 0xFFFFFFFF;
-	exp->mask.dst.u.udp.port = 0xFFFF;
+	exp->mask.dst.ip = htonl(0xFFFFFFFF);
+	exp->mask.dst.u.udp.port = htons(0xFFFF);
 	exp->mask.dst.protonum = 0xFF;
 
 	exp->expectfn = NULL;
@@ -349,7 +349,7 @@
 	const char *dptr;
 	int ret = NF_ACCEPT;
 	int matchoff, matchlen;
-	u_int32_t ipaddr;
+	__be32 ipaddr;
 	u_int16_t port;
 
 	/* No Data ? */
@@ -439,7 +439,7 @@
 
 		sip[i].tuple.dst.protonum = IPPROTO_UDP;
 		sip[i].tuple.src.u.udp.port = htons(ports[i]);
-		sip[i].mask.src.u.udp.port = 0xFFFF;
+		sip[i].mask.src.u.udp.port = htons(0xFFFF);
 		sip[i].mask.dst.protonum = 0xFF;
 		sip[i].max_expected = 2;
 		sip[i].timeout = 3 * 60; /* 3 minutes */
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index 7e33d3b..fe0b634 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -70,10 +70,10 @@
 			return NF_DROP;
 
 		exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-		exp->mask.src.ip = 0xffffffff;
+		exp->mask.src.ip = htonl(0xffffffff);
 		exp->mask.src.u.udp.port = 0;
-		exp->mask.dst.ip = 0xffffffff;
-		exp->mask.dst.u.udp.port = 0xffff;
+		exp->mask.dst.ip = htonl(0xffffffff);
+		exp->mask.dst.u.udp.port = htons(0xffff);
 		exp->mask.dst.protonum = 0xff;
 		exp->expectfn = NULL;
 		exp->flags = 0;
@@ -129,7 +129,7 @@
 		tftp[i].tuple.dst.protonum = IPPROTO_UDP;
 		tftp[i].tuple.src.u.udp.port = htons(ports[i]);
 		tftp[i].mask.dst.protonum = 0xFF;
-		tftp[i].mask.src.u.udp.port = 0xFFFF;
+		tftp[i].mask.src.u.udp.port = htons(0xFFFF);
 		tftp[i].max_expected = 1;
 		tftp[i].timeout = 5 * 60; /* 5 minutes */
 		tftp[i].me = THIS_MODULE;
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 71f3e09..4b6260a 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -82,7 +82,7 @@
 hash_by_src(const struct ip_conntrack_tuple *tuple)
 {
 	/* Original src, to ensure we map it consistently if poss. */
-	return jhash_3words(tuple->src.ip, tuple->src.u.all,
+	return jhash_3words((__force u32)tuple->src.ip, tuple->src.u.all,
 			    tuple->dst.protonum, 0) % ip_nat_htable_size;
 }
 
@@ -190,7 +190,7 @@
 		    const struct ip_conntrack *conntrack,
 		    enum ip_nat_manip_type maniptype)
 {
-	u_int32_t *var_ipp;
+	__be32 *var_ipp;
 	/* Host order */
 	u_int32_t minip, maxip, j;
 
@@ -217,7 +217,7 @@
 	 * like this), even across reboots. */
 	minip = ntohl(range->min_ip);
 	maxip = ntohl(range->max_ip);
-	j = jhash_2words(tuple->src.ip, tuple->dst.ip, 0);
+	j = jhash_2words((__force u32)tuple->src.ip, (__force u32)tuple->dst.ip, 0);
 	*var_ipp = htonl(minip + j % (maxip - minip + 1));
 }
 
@@ -534,9 +534,9 @@
 ip_nat_port_range_to_nfattr(struct sk_buff *skb, 
 			    const struct ip_nat_range *range)
 {
-	NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(u_int16_t),
+	NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(__be16),
 		&range->min.tcp.port);
-	NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(u_int16_t),
+	NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(__be16),
 		&range->max.tcp.port);
 
 	return 0;
@@ -555,7 +555,7 @@
 	if (tb[CTA_PROTONAT_PORT_MIN-1]) {
 		ret = 1;
 		range->min.tcp.port = 
-			*(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
+			*(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
 	}
 	
 	if (!tb[CTA_PROTONAT_PORT_MAX-1]) {
@@ -564,7 +564,7 @@
 	} else {
 		ret = 1;
 		range->max.tcp.port = 
-			*(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
+			*(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
 	}
 
 	return ret;
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index 3328fc5..a71c233 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -34,7 +34,7 @@
 
 static int
 mangle_rfc959_packet(struct sk_buff **pskb,
-		     u_int32_t newip,
+		     __be32 newip,
 		     u_int16_t port,
 		     unsigned int matchoff,
 		     unsigned int matchlen,
@@ -57,7 +57,7 @@
 /* |1|132.235.1.2|6275| */
 static int
 mangle_eprt_packet(struct sk_buff **pskb,
-		   u_int32_t newip,
+		   __be32 newip,
 		   u_int16_t port,
 		   unsigned int matchoff,
 		   unsigned int matchlen,
@@ -79,7 +79,7 @@
 /* |1|132.235.1.2|6275| */
 static int
 mangle_epsv_packet(struct sk_buff **pskb,
-		   u_int32_t newip,
+		   __be32 newip,
 		   u_int16_t port,
 		   unsigned int matchoff,
 		   unsigned int matchlen,
@@ -98,7 +98,7 @@
 					matchlen, buffer, strlen(buffer));
 }
 
-static int (*mangle[])(struct sk_buff **, u_int32_t, u_int16_t,
+static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
 		     unsigned int,
 		     unsigned int,
 		     struct ip_conntrack *,
@@ -120,7 +120,7 @@
 			       struct ip_conntrack_expect *exp,
 			       u32 *seq)
 {
-	u_int32_t newip;
+	__be32 newip;
 	u_int16_t port;
 	int dir = CTINFO2DIR(ctinfo);
 	struct ip_conntrack *ct = exp->master;
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 7f6a759..3bf8584 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -189,7 +189,7 @@
 					   		datalen, 0));
 	} else
 		tcph->check = nf_proto_csum_update(*pskb,
-						   htons(oldlen) ^ 0xFFFF,
+						   htons(oldlen) ^ htons(0xFFFF),
 						   htons(datalen),
 						   tcph->check, 1);
 
@@ -267,7 +267,7 @@
 			udph->check = -1;
 	} else
 		udph->check = nf_proto_csum_update(*pskb,
-						   htons(oldlen) ^ 0xFFFF,
+						   htons(oldlen) ^ htons(0xFFFF),
 						   htons(datalen),
 						   udph->check, 1);
 	return 1;
@@ -283,27 +283,25 @@
 	    struct ip_nat_seq *natseq)
 {
 	while (sackoff < sackend) {
-		struct tcp_sack_block *sack;
-		u_int32_t new_start_seq, new_end_seq;
+		struct tcp_sack_block_wire *sack;
+		__be32 new_start_seq, new_end_seq;
 
 		sack = (void *)skb->data + sackoff;
 		if (after(ntohl(sack->start_seq) - natseq->offset_before,
 			  natseq->correction_pos))
-			new_start_seq = ntohl(sack->start_seq) 
-					- natseq->offset_after;
+			new_start_seq = htonl(ntohl(sack->start_seq)
+					- natseq->offset_after);
 		else
-			new_start_seq = ntohl(sack->start_seq) 
-					- natseq->offset_before;
-		new_start_seq = htonl(new_start_seq);
+			new_start_seq = htonl(ntohl(sack->start_seq)
+					- natseq->offset_before);
 
 		if (after(ntohl(sack->end_seq) - natseq->offset_before,
 			  natseq->correction_pos))
-			new_end_seq = ntohl(sack->end_seq)
-				      - natseq->offset_after;
+			new_end_seq = htonl(ntohl(sack->end_seq)
+				      - natseq->offset_after);
 		else
-			new_end_seq = ntohl(sack->end_seq)
-				      - natseq->offset_before;
-		new_end_seq = htonl(new_end_seq);
+			new_end_seq = htonl(ntohl(sack->end_seq)
+				      - natseq->offset_before);
 
 		DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
 			ntohl(sack->start_seq), new_start_seq,
@@ -375,7 +373,8 @@
 		  enum ip_conntrack_info ctinfo)
 {
 	struct tcphdr *tcph;
-	int dir, newseq, newack;
+	int dir;
+	__be32 newseq, newack;
 	struct ip_nat_seq *this_way, *other_way;	
 
 	dir = CTINFO2DIR(ctinfo);
@@ -388,17 +387,15 @@
 
 	tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
 	if (after(ntohl(tcph->seq), this_way->correction_pos))
-		newseq = ntohl(tcph->seq) + this_way->offset_after;
+		newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
 	else
-		newseq = ntohl(tcph->seq) + this_way->offset_before;
-	newseq = htonl(newseq);
+		newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);
 
 	if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
 		  other_way->correction_pos))
-		newack = ntohl(tcph->ack_seq) - other_way->offset_after;
+		newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
 	else
-		newack = ntohl(tcph->ack_seq) - other_way->offset_before;
-	newack = htonl(newack);
+		newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
 
 	tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq,
 					   tcph->check, 0);
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index 419b878..4a7d344 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -32,13 +32,13 @@
 /****************************************************************************/
 static int set_addr(struct sk_buff **pskb,
 		    unsigned char **data, int dataoff,
-		    unsigned int addroff, u_int32_t ip, u_int16_t port)
+		    unsigned int addroff, __be32 ip, u_int16_t port)
 {
 	enum ip_conntrack_info ctinfo;
 	struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
 	struct {
-		u_int32_t ip;
-		u_int16_t port;
+		__be32 ip;
+		__be16 port;
 	} __attribute__ ((__packed__)) buf;
 	struct tcphdr _tcph, *th;
 
@@ -86,7 +86,7 @@
 static int set_h225_addr(struct sk_buff **pskb,
 			 unsigned char **data, int dataoff,
 			 TransportAddress * addr,
-			 u_int32_t ip, u_int16_t port)
+			 __be32 ip, u_int16_t port)
 {
 	return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
 }
@@ -95,7 +95,7 @@
 static int set_h245_addr(struct sk_buff **pskb,
 			 unsigned char **data, int dataoff,
 			 H245_TransportAddress * addr,
-			 u_int32_t ip, u_int16_t port)
+			 __be32 ip, u_int16_t port)
 {
 	return set_addr(pskb, data, dataoff,
 			addr->unicastAddress.iPAddress.network, ip, port);
@@ -110,7 +110,7 @@
 	struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
 	int dir = CTINFO2DIR(ctinfo);
 	int i;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 
 	for (i = 0; i < count; i++) {
@@ -164,7 +164,7 @@
 {
 	int dir = CTINFO2DIR(ctinfo);
 	int i;
-	u_int32_t ip;
+	__be32 ip;
 	u_int16_t port;
 
 	for (i = 0; i < count; i++) {
@@ -433,7 +433,7 @@
 	struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
 	int dir = CTINFO2DIR(ctinfo);
 	u_int16_t nated_port = port;
-	u_int32_t ip;
+	__be32 ip;
 
 	/* Set expectations for NAT */
 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index 2ff5788..329fdcd 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -51,7 +51,7 @@
 
 #define IP_NAT_PPTP_VERSION "3.0"
 
-#define REQ_CID(req, off)		(*(u_int16_t *)((char *)(req) + (off)))
+#define REQ_CID(req, off)		(*(__be16 *)((char *)(req) + (off)))
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
index ec50cc2..3f6efc1 100644
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -67,7 +67,7 @@
 
 	hdr = (struct icmphdr *)((*pskb)->data + hdroff);
 	hdr->checksum = nf_proto_csum_update(*pskb,
-					     hdr->un.echo.id ^ 0xFFFF,
+					     hdr->un.echo.id ^ htons(0xFFFF),
 					     tuple->src.u.icmp.id,
 					     hdr->checksum, 0);
 	hdr->un.echo.id = tuple->src.u.icmp.id;
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index 72a6307..12deb13b 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -24,7 +24,7 @@
 	     const union ip_conntrack_manip_proto *min,
 	     const union ip_conntrack_manip_proto *max)
 {
-	u_int16_t port;
+	__be16 port;
 
 	if (maniptype == IP_NAT_MANIP_SRC)
 		port = tuple->src.u.tcp.port;
@@ -42,7 +42,7 @@
 		 const struct ip_conntrack *conntrack)
 {
 	static u_int16_t port;
-	u_int16_t *portptr;
+	__be16 *portptr;
 	unsigned int range_size, min, i;
 
 	if (maniptype == IP_NAT_MANIP_SRC)
@@ -93,8 +93,8 @@
 	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
 	struct tcphdr *hdr;
 	unsigned int hdroff = iphdroff + iph->ihl*4;
-	u32 oldip, newip;
-	u16 *portptr, newport, oldport;
+	__be32 oldip, newip;
+	__be16 *portptr, newport, oldport;
 	int hdrsize = 8; /* TCP connection tracking guarantees this much */
 
 	/* this could be a inner header returned in icmp packet; in such
@@ -130,7 +130,7 @@
 		return 1;
 
 	hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1);
-	hdr->check = nf_proto_csum_update(*pskb, oldport ^ 0xFFFF, newport,
+	hdr->check = nf_proto_csum_update(*pskb, oldport ^ htons(0xFFFF), newport,
 					  hdr->check, 0);
 	return 1;
 }
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index 5da196a..4bbec77 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -24,7 +24,7 @@
 	     const union ip_conntrack_manip_proto *min,
 	     const union ip_conntrack_manip_proto *max)
 {
-	u_int16_t port;
+	__be16 port;
 
 	if (maniptype == IP_NAT_MANIP_SRC)
 		port = tuple->src.u.udp.port;
@@ -42,7 +42,7 @@
 		 const struct ip_conntrack *conntrack)
 {
 	static u_int16_t port;
-	u_int16_t *portptr;
+	__be16 *portptr;
 	unsigned int range_size, min, i;
 
 	if (maniptype == IP_NAT_MANIP_SRC)
@@ -91,8 +91,8 @@
 	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
 	struct udphdr *hdr;
 	unsigned int hdroff = iphdroff + iph->ihl*4;
-	u32 oldip, newip;
-	u16 *portptr, newport;
+	__be32 oldip, newip;
+	__be16 *portptr, newport;
 
 	if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
 		return 0;
@@ -118,7 +118,7 @@
 		hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip,
 						  hdr->check, 1);
 		hdr->check = nf_proto_csum_update(*pskb,
-						  *portptr ^ 0xFFFF, newport,
+						  *portptr ^ htons(0xFFFF), newport,
 						  hdr->check, 0);
 		if (!hdr->check)
 			hdr->check = -1;
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index 7b70383..a176aa3 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -119,7 +119,7 @@
 }
 
 /* Before 2.6.11 we did implicit source NAT if required. Warn about change. */
-static void warn_if_extra_mangle(u32 dstip, u32 srcip)
+static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
 {
 	static int warned = 0;
 	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
@@ -205,7 +205,7 @@
 	   per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
 	   Use reply in case it's already been mangled (eg local packet).
 	*/
-	u_int32_t ip
+	__be32 ip
 		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
 		   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
 		   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
@@ -222,7 +222,7 @@
                              struct ip_nat_info *info,
                              unsigned int hooknum)
 {
-	u_int32_t ip
+	__be32 ip
 		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
 		   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
 		   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 6ffba63..71fc273 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -60,8 +60,8 @@
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
 	unsigned int bufflen, dataoff;
-	u_int32_t ip;
-	u_int16_t port;
+	__be32 ip;
+	__be16 port;
 
 	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
 
@@ -159,7 +159,7 @@
 static unsigned int mangle_sdp(struct sk_buff **pskb,
 			       enum ip_conntrack_info ctinfo,
 			       struct ip_conntrack *ct,
-			       u_int32_t newip, u_int16_t port,
+			       __be32 newip, u_int16_t port,
 			       const char *dptr)
 {
 	char buffer[sizeof("nnn.nnn.nnn.nnn")];
@@ -195,7 +195,7 @@
 {
 	struct ip_conntrack *ct = exp->master;
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-	u_int32_t newip;
+	__be32 newip;
 	u_int16_t port;
 
 	DEBUGP("ip_nat_sdp():\n");
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 18b7fbd..168f45f 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -1211,7 +1211,7 @@
                           struct sk_buff **pskb)
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
-	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
+	struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
 	u_int16_t udplen = ntohs(udph->len);
 	u_int16_t paylen = udplen - sizeof(struct udphdr);
 	int dir = CTINFO2DIR(ctinfo);
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 9c577db..021395b 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -191,7 +191,7 @@
           int (*okfn)(struct sk_buff *))
 {
 	unsigned int ret;
-	u_int32_t daddr = (*pskb)->nh.iph->daddr;
+	__be32 daddr = (*pskb)->nh.iph->daddr;
 
 	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
 	if (ret != NF_DROP && ret != NF_STOLEN
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 4158966..7a29d6e 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -52,7 +52,7 @@
 	atomic_t entries;			/* number of entries/rules
 						 * referencing us */
 
-	u_int32_t clusterip;			/* the IP address */
+	__be32 clusterip;			/* the IP address */
 	u_int8_t clustermac[ETH_ALEN];		/* the MAC address */
 	struct net_device *dev;			/* device */
 	u_int16_t num_total_nodes;		/* total number of nodes */
@@ -119,7 +119,7 @@
 }
 
 static struct clusterip_config *
-__clusterip_config_find(u_int32_t clusterip)
+__clusterip_config_find(__be32 clusterip)
 {
 	struct list_head *pos;
 
@@ -136,7 +136,7 @@
 }
 
 static inline struct clusterip_config *
-clusterip_config_find_get(u_int32_t clusterip, int entry)
+clusterip_config_find_get(__be32 clusterip, int entry)
 {
 	struct clusterip_config *c;
 
@@ -166,7 +166,7 @@
 }
 
 static struct clusterip_config *
-clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
+clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
 			struct net_device *dev)
 {
 	struct clusterip_config *c;
@@ -387,7 +387,7 @@
 		return 0;
 
 	}
-	if (e->ip.dmsk.s_addr != 0xffffffff
+	if (e->ip.dmsk.s_addr != htonl(0xffffffff)
 	    || e->ip.dst.s_addr == 0) {
 		printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
 		return 0;
@@ -476,9 +476,9 @@
 /* hardcoded for 48bit ethernet and 32bit ipv4 addresses */
 struct arp_payload {
 	u_int8_t src_hw[ETH_ALEN];
-	u_int32_t src_ip;
+	__be32 src_ip;
 	u_int8_t dst_hw[ETH_ALEN];
-	u_int32_t dst_ip;
+	__be32 dst_ip;
 } __attribute__ ((packed));
 
 #ifdef CLUSTERIP_DEBUG
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 23f9c7e..12a818a 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;
-	u_int16_t oldtos;
+	__be16 oldtos;
 
 	if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
 		if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -37,7 +37,7 @@
 		oldtos = iph->tos;
 		iph->tos &= ~IPT_ECN_IP_MASK;
 		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
-		iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos,
+		iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
 					    iph->check);
 	} 
 	return 1;
@@ -48,7 +48,7 @@
 set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
 	struct tcphdr _tcph, *tcph;
-	u_int16_t oldval;
+	__be16 oldval;
 
 	/* Not enought header? */
 	tcph = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
@@ -66,15 +66,15 @@
 		return 0;
 	tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4;
 
-	oldval = ((u_int16_t *)tcph)[6];
+	oldval = ((__be16 *)tcph)[6];
 	if (einfo->operation & IPT_ECN_OP_SET_ECE)
 		tcph->ece = einfo->proto.tcp.ece;
 	if (einfo->operation & IPT_ECN_OP_SET_CWR)
 		tcph->cwr = einfo->proto.tcp.cwr;
 
 	tcph->check = nf_proto_csum_update((*pskb),
-					   oldval ^ 0xFFFF,
-					   ((u_int16_t *)tcph)[6],
+					   oldval ^ htons(0xFFFF),
+					   ((__be16 *)tcph)[6],
 					   tcph->check, 0);
 	return 1;
 }
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index bc65168..3dbfcfa 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -70,7 +70,7 @@
 	const struct ip_nat_multi_range_compat *mr;
 	struct ip_nat_range newrange;
 	struct rtable *rt;
-	u_int32_t newsrc;
+	__be32 newsrc;
 
 	IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
 
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index beb2914..58a88f2 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -58,7 +58,7 @@
 {
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
-	u_int32_t new_ip, netmask;
+	__be32 new_ip, netmask;
 	const struct ip_nat_multi_range_compat *mr = targinfo;
 	struct ip_nat_range newrange;
 
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index f03d436..c0dcfe9 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -61,7 +61,7 @@
 {
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
-	u_int32_t newdst;
+	__be32 newdst;
 	const struct ip_nat_multi_range_compat *mr = targinfo;
 	struct ip_nat_range newrange;
 
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index b81821e..fd0c05e 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -104,8 +104,8 @@
 	struct iphdr *iph = oldskb->nh.iph;
 	struct tcphdr _otcph, *oth, *tcph;
 	struct rtable *rt;
-	u_int16_t tmp_port;
-	u_int32_t tmp_addr;
+	__be16 tmp_port;
+	__be32 tmp_addr;
 	int needs_ack;
 	int hh_len;
 
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index efbcb11..b38b133 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -135,7 +135,8 @@
 {
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
-	u_int32_t tmpip, aindex, new_ip;
+	u_int32_t tmpip, aindex;
+	__be32 new_ip;
 	const struct ipt_same_info *same = targinfo;
 	struct ip_nat_range newrange;
 	const struct ip_conntrack_tuple *t;
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 4246c43..108b6b7 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -42,7 +42,8 @@
 	const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
 	struct tcphdr *tcph;
 	struct iphdr *iph;
-	u_int16_t tcplen, newtotlen, oldval, newmss;
+	u_int16_t tcplen, newmss;
+	__be16 newtotlen, oldval;
 	unsigned int i;
 	u_int8_t *opt;
 
@@ -97,7 +98,7 @@
 			opt[i+3] = (newmss & 0x00ff);
 
 			tcph->check = nf_proto_csum_update(*pskb,
-							   htons(oldmss)^0xFFFF,
+							   htons(oldmss)^htons(0xFFFF),
 							   htons(newmss),
 							   tcph->check, 0);
 			return IPT_CONTINUE;
@@ -126,7 +127,7 @@
 	memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
 
 	tcph->check = nf_proto_csum_update(*pskb,
-					   htons(tcplen) ^ 0xFFFF,
+					   htons(tcplen) ^ htons(0xFFFF),
 				           htons(tcplen + TCPOLEN_MSS),
 					   tcph->check, 1);
 	opt[0] = TCPOPT_MSS;
@@ -134,18 +135,18 @@
 	opt[2] = (newmss & 0xff00) >> 8;
 	opt[3] = (newmss & 0x00ff);
 
-	tcph->check = nf_proto_csum_update(*pskb, ~0, *((u_int32_t *)opt),
+	tcph->check = nf_proto_csum_update(*pskb, htonl(~0), *((__be32 *)opt),
 					   tcph->check, 0);
 
-	oldval = ((u_int16_t *)tcph)[6];
+	oldval = ((__be16 *)tcph)[6];
 	tcph->doff += TCPOLEN_MSS/4;
 	tcph->check = nf_proto_csum_update(*pskb,
-					   oldval ^ 0xFFFF,
-					   ((u_int16_t *)tcph)[6],
+					   oldval ^ htons(0xFFFF),
+					   ((__be16 *)tcph)[6],
 					   tcph->check, 0);
 
 	newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
-	iph->check = nf_csum_update(iph->tot_len ^ 0xFFFF,
+	iph->check = nf_csum_update(iph->tot_len ^ htons(0xFFFF),
 				    newtotlen, iph->check);
 	iph->tot_len = newtotlen;
 	return IPT_CONTINUE;
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 471a4c4..6b8b14c 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;
-	u_int16_t oldtos;
+	__be16 oldtos;
 
 	if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
 		if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -38,7 +38,7 @@
 		iph = (*pskb)->nh.iph;
 		oldtos = iph->tos;
 		iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
-		iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos,
+		iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
 					    iph->check);
 	}
 	return IPT_CONTINUE;
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 96e79cc..ac9517d 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -54,8 +54,8 @@
 	}
 
 	if (new_ttl != iph->ttl) {
-		iph->check = nf_csum_update(ntohs((iph->ttl << 8)) ^ 0xFFFF,
-					    ntohs(new_ttl << 8),
+		iph->check = nf_csum_update(htons((iph->ttl << 8)) ^ htons(0xFFFF),
+					    htons(new_ttl << 8),
 					    iph->check);
 		iph->ttl = new_ttl;
 	}
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index 893dae2..7b60eb7 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -22,7 +22,7 @@
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_DESCRIPTION("iptables addrtype match");
 
-static inline int match_type(u_int32_t addr, u_int16_t mask)
+static inline int match_type(__be32 addr, u_int16_t mask)
 {
 	return !!(mask & (1 << inet_addr_type(addr)));
 }
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 4f73a61..33ccdbf 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -50,11 +50,11 @@
 /* hash table crap */
 
 struct dsthash_dst {
-	u_int32_t src_ip;
-	u_int32_t dst_ip;
+	__be32 src_ip;
+	__be32 dst_ip;
 	/* ports have to be consecutive !!! */
-	u_int16_t src_port;
-	u_int16_t dst_port;
+	__be16 src_port;
+	__be16 dst_port;
 };
 
 struct dsthash_ent {
@@ -106,8 +106,10 @@
 static inline u_int32_t
 hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst)
 {
-	return (jhash_3words(dst->dst_ip, (dst->dst_port<<16 | dst->src_port), 
-			     dst->src_ip, ht->rnd) % ht->cfg.size);
+	return (jhash_3words((__force u32)dst->dst_ip,
+			    ((__force u32)dst->dst_port<<16 |
+			     (__force u32)dst->src_port),
+			     (__force u32)dst->src_ip, ht->rnd) % ht->cfg.size);
 }
 
 static inline struct dsthash_ent *
@@ -406,7 +408,7 @@
 		dst.src_ip = skb->nh.iph->saddr;
 	if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT
 	    ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
-		u_int16_t _ports[2], *ports;
+		__be16 _ports[2], *ports;
 
 		switch (skb->nh.iph->protocol) {
 		case IPPROTO_TCP:
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 32ae8d7..126db44 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -50,11 +50,10 @@
 MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/ipt_recent/* files");
 MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/ipt_recent/* files");
 
-
 struct recent_entry {
 	struct list_head	list;
 	struct list_head	lru_list;
-	u_int32_t		addr;
+	__be32			addr;
 	u_int8_t		ttl;
 	u_int8_t		index;
 	u_int16_t		nstamps;
@@ -85,17 +84,17 @@
 static u_int32_t hash_rnd;
 static int hash_rnd_initted;
 
-static unsigned int recent_entry_hash(u_int32_t addr)
+static unsigned int recent_entry_hash(__be32 addr)
 {
 	if (!hash_rnd_initted) {
 		get_random_bytes(&hash_rnd, 4);
 		hash_rnd_initted = 1;
 	}
-	return jhash_1word(addr, hash_rnd) & (ip_list_hash_size - 1);
+	return jhash_1word((__force u32)addr, hash_rnd) & (ip_list_hash_size - 1);
 }
 
 static struct recent_entry *
-recent_entry_lookup(const struct recent_table *table, u_int32_t addr, u_int8_t ttl)
+recent_entry_lookup(const struct recent_table *table, __be32 addr, u_int8_t ttl)
 {
 	struct recent_entry *e;
 	unsigned int h;
@@ -116,7 +115,7 @@
 }
 
 static struct recent_entry *
-recent_entry_init(struct recent_table *t, u_int32_t addr, u_int8_t ttl)
+recent_entry_init(struct recent_table *t, __be32 addr, u_int8_t ttl)
 {
 	struct recent_entry *e;
 
@@ -178,7 +177,7 @@
 	const struct ipt_recent_info *info = matchinfo;
 	struct recent_table *t;
 	struct recent_entry *e;
-	u_int32_t addr;
+	__be32 addr;
 	u_int8_t ttl;
 	int ret = info->invert;
 
@@ -406,7 +405,7 @@
 	struct recent_table *t = pde->data;
 	struct recent_entry *e;
 	char buf[sizeof("+255.255.255.255")], *c = buf;
-	u_int32_t addr;
+	__be32 addr;
 	int add;
 
 	if (size > sizeof(buf))
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 79336cb..e62ea2b 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -131,7 +131,7 @@
 {
 	unsigned int ret;
 	u_int8_t tos;
-	u_int32_t saddr, daddr;
+	__be32 saddr, daddr;
 	unsigned long nfmark;
 
 	/* root is playing with raw sockets. */
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 0e935b4..b430cf2 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -381,8 +381,8 @@
 	struct ipcm_cookie ipc;
 	struct rtable *rt = NULL;
 	int free = 0;
-	u32 daddr;
-	u32 saddr;
+	__be32 daddr;
+	__be32 saddr;
 	u8  tos;
 	int err;
 
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 20ffe8e..c41ddba 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -261,6 +261,10 @@
 		& rt_hash_mask);
 }
 
+#define rt_hash(daddr, saddr, idx) \
+	rt_hash_code((__force u32)(__be32)(daddr),\
+		     (__force u32)(__be32)(saddr) ^ ((idx) << 5))
+
 #ifdef CONFIG_PROC_FS
 struct rt_cache_iter_state {
 	int bucket;
@@ -1074,7 +1078,7 @@
 	u32 salt;
 
 	spin_lock_bh(&ip_fb_id_lock);
-	salt = secure_ip_id(ip_fallback_id ^ iph->daddr);
+	salt = secure_ip_id((__force __be32)ip_fallback_id ^ iph->daddr);
 	iph->id = htons(salt & 0xFFFF);
 	ip_fallback_id = salt;
 	spin_unlock_bh(&ip_fb_id_lock);
@@ -1118,13 +1122,13 @@
 	spin_unlock_bh(rt_hash_lock_addr(hash));
 }
 
-void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
-		    u32 saddr, struct net_device *dev)
+void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+		    __be32 saddr, struct net_device *dev)
 {
 	int i, k;
 	struct in_device *in_dev = in_dev_get(dev);
 	struct rtable *rth, **rthp;
-	u32  skeys[2] = { saddr, 0 };
+	__be32  skeys[2] = { saddr, 0 };
 	int  ikeys[2] = { dev->ifindex, 0 };
 	struct netevent_redirect netevent;
 
@@ -1147,8 +1151,7 @@
 
 	for (i = 0; i < 2; i++) {
 		for (k = 0; k < 2; k++) {
-			unsigned hash = rt_hash_code(daddr,
-						     skeys[i] ^ (ikeys[k] << 5));
+			unsigned hash = rt_hash(daddr, skeys[i], ikeys[k]);
 
 			rthp=&rt_hash_table[hash].chain;
 
@@ -1260,9 +1263,8 @@
 			ret = NULL;
 		} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
 			   rt->u.dst.expires) {
-			unsigned hash = rt_hash_code(rt->fl.fl4_dst,
-						     rt->fl.fl4_src ^
-							(rt->fl.oif << 5));
+			unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
+						rt->fl.oif);
 #if RT_CACHE_DEBUG >= 1
 			printk(KERN_DEBUG "ip_rt_advice: redirect to "
 					  "%u.%u.%u.%u/%02x dropped\n",
@@ -1397,15 +1399,15 @@
 	int i;
 	unsigned short old_mtu = ntohs(iph->tot_len);
 	struct rtable *rth;
-	u32  skeys[2] = { iph->saddr, 0, };
-	u32  daddr = iph->daddr;
+	__be32  skeys[2] = { iph->saddr, 0, };
+	__be32  daddr = iph->daddr;
 	unsigned short est_mtu = 0;
 
 	if (ipv4_config.no_pmtu_disc)
 		return 0;
 
 	for (i = 0; i < 2; i++) {
-		unsigned hash = rt_hash_code(daddr, skeys[i]);
+		unsigned hash = rt_hash(daddr, skeys[i], 0);
 
 		rcu_read_lock();
 		for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -1530,7 +1532,7 @@
 
 void ip_rt_get_source(u8 *addr, struct rtable *rt)
 {
-	u32 src;
+	__be32 src;
 	struct fib_result res;
 
 	if (rt->fl.iif == 0)
@@ -1596,12 +1598,12 @@
         rt->rt_type = res->type;
 }
 
-static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
+static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 				u8 tos, struct net_device *dev, int our)
 {
 	unsigned hash;
 	struct rtable *rth;
-	u32 spec_dst;
+	__be32 spec_dst;
 	struct in_device *in_dev = in_dev_get(dev);
 	u32 itag = 0;
 
@@ -1665,7 +1667,7 @@
 	RT_CACHE_STAT_INC(in_slow_mc);
 
 	in_dev_put(in_dev);
-	hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5));
+	hash = rt_hash(daddr, saddr, dev->ifindex);
 	return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst);
 
 e_nobufs:
@@ -1681,8 +1683,8 @@
 static void ip_handle_martian_source(struct net_device *dev,
 				     struct in_device *in_dev,
 				     struct sk_buff *skb,
-				     u32 daddr,
-				     u32 saddr) 
+				     __be32 daddr,
+				     __be32 saddr)
 {
 	RT_CACHE_STAT_INC(in_martian_src);
 #ifdef CONFIG_IP_ROUTE_VERBOSE
@@ -1712,7 +1714,7 @@
 static inline int __mkroute_input(struct sk_buff *skb, 
 				  struct fib_result* res, 
 				  struct in_device *in_dev, 
-				  u32 daddr, u32 saddr, u32 tos, 
+				  __be32 daddr, __be32 saddr, u32 tos,
 				  struct rtable **result) 
 {
 
@@ -1720,7 +1722,8 @@
 	int err;
 	struct in_device *out_dev;
 	unsigned flags = 0;
-	u32 spec_dst, itag;
+	__be32 spec_dst;
+	u32 itag;
 
 	/* get a working reference to the output device */
 	out_dev = in_dev_get(FIB_RES_DEV(*res));
@@ -1813,7 +1816,7 @@
 				       struct fib_result* res, 
 				       const struct flowi *fl,
 				       struct in_device *in_dev,
-				       u32 daddr, u32 saddr, u32 tos)
+				       __be32 daddr, __be32 saddr, u32 tos)
 {
 	struct rtable* rth = NULL;
 	int err;
@@ -1830,7 +1833,7 @@
 		return err;
 
 	/* put it into the cache */
-	hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5));
+	hash = rt_hash(daddr, saddr, fl->iif);
 	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);	
 }
 
@@ -1838,7 +1841,7 @@
 				   struct fib_result* res, 
 				   const struct flowi *fl,
 				   struct in_device *in_dev,
-				   u32 daddr, u32 saddr, u32 tos)
+				   __be32 daddr, __be32 saddr, u32 tos)
 {
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
 	struct rtable* rth = NULL, *rtres;
@@ -1871,7 +1874,7 @@
 			return err;
 
 		/* put it into the cache */
-		hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5));
+		hash = rt_hash(daddr, saddr, fl->iif);
 		err = rt_intern_hash(hash, rth, &rtres);
 		if (err)
 			return err;
@@ -1901,7 +1904,7 @@
  *	2. IP spoofing attempts are filtered with 100% of guarantee.
  */
 
-static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
+static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 			       u8 tos, struct net_device *dev)
 {
 	struct fib_result res;
@@ -1920,7 +1923,7 @@
 	u32		itag = 0;
 	struct rtable * rth;
 	unsigned	hash;
-	u32		spec_dst;
+	__be32		spec_dst;
 	int		err = -EINVAL;
 	int		free_res = 0;
 
@@ -1936,7 +1939,7 @@
 	if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr))
 		goto martian_source;
 
-	if (daddr == 0xFFFFFFFF || (saddr == 0 && daddr == 0))
+	if (daddr == htonl(0xFFFFFFFF) || (saddr == 0 && daddr == 0))
 		goto brd_input;
 
 	/* Accept zero addresses only to limited broadcast;
@@ -2048,7 +2051,7 @@
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
 	rth->rt_type	= res.type;
-	hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5));
+	hash = rt_hash(daddr, saddr, fl.iif);
 	err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
 	goto done;
 
@@ -2087,7 +2090,7 @@
 	goto e_inval;
 }
 
-int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
+int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 		   u8 tos, struct net_device *dev)
 {
 	struct rtable * rth;
@@ -2095,7 +2098,7 @@
 	int iif = dev->ifindex;
 
 	tos &= IPTOS_RT_MASK;
-	hash = rt_hash_code(daddr, saddr ^ (iif << 5));
+	hash = rt_hash(daddr, saddr, iif);
 
 	rcu_read_lock();
 	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -2169,7 +2172,7 @@
 	if (LOOPBACK(fl->fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
 		return -EINVAL;
 
-	if (fl->fl4_dst == 0xFFFFFFFF)
+	if (fl->fl4_dst == htonl(0xFFFFFFFF))
 		res->type = RTN_BROADCAST;
 	else if (MULTICAST(fl->fl4_dst))
 		res->type = RTN_MULTICAST;
@@ -2293,8 +2296,7 @@
 	int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
 	unsigned hash;
 	if (err == 0) {
-		hash = rt_hash_code(oldflp->fl4_dst, 
-				    oldflp->fl4_src ^ (oldflp->oif << 5));
+		hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif);
 		err = rt_intern_hash(hash, rth, rp);
 	}
 	
@@ -2336,9 +2338,8 @@
 			if (err != 0)
 				goto cleanup;
 
-			hash = rt_hash_code(oldflp->fl4_dst, 
-					    oldflp->fl4_src ^
-					    (oldflp->oif << 5));
+			hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src,
+					oldflp->oif);
 			err = rt_intern_hash(hash, rth, rp);
 
 			/* forward hop information to multipath impl. */
@@ -2417,7 +2418,7 @@
 		 */
 
 		if (oldflp->oif == 0
-		    && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF)) {
+		    && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
 			/* Special hack: user can direct multicasts
 			   and limited broadcast via necessary interface
 			   without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
@@ -2454,7 +2455,7 @@
 			goto out;	/* Wrong error code */
 		}
 
-		if (LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF) {
+		if (LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF)) {
 			if (!fl.fl4_src)
 				fl.fl4_src = inet_select_addr(dev_out, 0,
 							      RT_SCOPE_LINK);
@@ -2567,7 +2568,7 @@
 	unsigned hash;
 	struct rtable *rth;
 
-	hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5));
+	hash = rt_hash(flp->fl4_dst, flp->fl4_src, flp->oif);
 
 	rcu_read_lock_bh();
 	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -2660,11 +2661,11 @@
 	if (rt->rt_flags & RTCF_NOTIFY)
 		r->rtm_flags |= RTM_F_NOTIFY;
 
-	NLA_PUT_U32(skb, RTA_DST, rt->rt_dst);
+	NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst);
 
 	if (rt->fl.fl4_src) {
 		r->rtm_src_len = 32;
-		NLA_PUT_U32(skb, RTA_SRC, rt->fl.fl4_src);
+		NLA_PUT_BE32(skb, RTA_SRC, rt->fl.fl4_src);
 	}
 	if (rt->u.dst.dev)
 		NLA_PUT_U32(skb, RTA_OIF, rt->u.dst.dev->ifindex);
@@ -2677,12 +2678,12 @@
 		NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
 #endif
 	if (rt->fl.iif)
-		NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_spec_dst);
+		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
 	else if (rt->rt_src != rt->fl.fl4_src)
-		NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_src);
+		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_src);
 
 	if (rt->rt_dst != rt->rt_gateway)
-		NLA_PUT_U32(skb, RTA_GATEWAY, rt->rt_gateway);
+		NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway);
 
 	if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
 		goto nla_put_failure;
@@ -2706,7 +2707,7 @@
 
 	if (rt->fl.iif) {
 #ifdef CONFIG_IP_MROUTE
-		u32 dst = rt->rt_dst;
+		__be32 dst = rt->rt_dst;
 
 		if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
 		    ipv4_devconf.mc_forwarding) {
@@ -2740,7 +2741,9 @@
 	struct rtmsg *rtm;
 	struct nlattr *tb[RTA_MAX+1];
 	struct rtable *rt = NULL;
-	u32 dst, src, iif;
+	__be32 dst = 0;
+	__be32 src = 0;
+	u32 iif;
 	int err;
 	struct sk_buff *skb;
 
@@ -2765,8 +2768,8 @@
 	skb->nh.iph->protocol = IPPROTO_ICMP;
 	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
-	src = tb[RTA_SRC] ? nla_get_u32(tb[RTA_SRC]) : 0;
-	dst = tb[RTA_DST] ? nla_get_u32(tb[RTA_DST]) : 0;
+	src = tb[RTA_SRC] ? nla_get_be32(tb[RTA_SRC]) : 0;
+	dst = tb[RTA_DST] ? nla_get_be32(tb[RTA_DST]) : 0;
 	iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
 
 	if (iif) {
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b3def0d..3f884ce 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -935,7 +935,7 @@
 	const struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
-	struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
+	struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2);
 	int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
 	int reord = tp->packets_out;
 	int prior_fackets;
@@ -2239,13 +2239,12 @@
 	return acked;
 }
 
-static u32 tcp_usrtt(const struct sk_buff *skb)
+static u32 tcp_usrtt(struct timeval *tv)
 {
-	struct timeval tv, now;
+	struct timeval now;
 
 	do_gettimeofday(&now);
-	skb_get_timestamp(skb, &tv);
-	return (now.tv_sec - tv.tv_sec) * 1000000 + (now.tv_usec - tv.tv_usec);
+	return (now.tv_sec - tv->tv_sec) * 1000000 + (now.tv_usec - tv->tv_usec);
 }
 
 /* Remove acknowledged frames from the retransmission queue. */
@@ -2260,6 +2259,7 @@
 	u32 pkts_acked = 0;
 	void (*rtt_sample)(struct sock *sk, u32 usrtt)
 		= icsk->icsk_ca_ops->rtt_sample;
+	struct timeval tv;
 
 	while ((skb = skb_peek(&sk->sk_write_queue)) &&
 	       skb != sk->sk_send_head) {
@@ -2308,8 +2308,7 @@
 				seq_rtt = -1;
 			} else if (seq_rtt < 0) {
 				seq_rtt = now - scb->when;
-				if (rtt_sample)
-					(*rtt_sample)(sk, tcp_usrtt(skb));
+				skb_get_timestamp(skb, &tv);
 			}
 			if (sacked & TCPCB_SACKED_ACKED)
 				tp->sacked_out -= tcp_skb_pcount(skb);
@@ -2322,8 +2321,7 @@
 			}
 		} else if (seq_rtt < 0) {
 			seq_rtt = now - scb->when;
-			if (rtt_sample)
-				(*rtt_sample)(sk, tcp_usrtt(skb));
+			skb_get_timestamp(skb, &tv);
 		}
 		tcp_dec_pcount_approx(&tp->fackets_out, skb);
 		tcp_packets_out_dec(tp, skb);
@@ -2335,6 +2333,8 @@
 	if (acked&FLAG_ACKED) {
 		tcp_ack_update_rtt(sk, acked, seq_rtt);
 		tcp_ack_packets_out(sk, tp);
+		if (rtt_sample && !(acked & FLAG_RETRANS_DATA_ACKED))
+			(*rtt_sample)(sk, tcp_usrtt(&tv));
 
 		if (icsk->icsk_ca_ops->pkts_acked)
 			icsk->icsk_ca_ops->pkts_acked(sk, pkts_acked);
@@ -2629,7 +2629,7 @@
 	  			switch(opcode) {
 				case TCPOPT_MSS:
 					if(opsize==TCPOLEN_MSS && th->syn && !estab) {
-						u16 in_mss = ntohs(get_unaligned((__u16 *)ptr));
+						u16 in_mss = ntohs(get_unaligned((__be16 *)ptr));
 						if (in_mss) {
 							if (opt_rx->user_mss && opt_rx->user_mss < in_mss)
 								in_mss = opt_rx->user_mss;
@@ -2657,8 +2657,8 @@
 						if ((estab && opt_rx->tstamp_ok) ||
 						    (!estab && sysctl_tcp_timestamps)) {
 							opt_rx->saw_tstamp = 1;
-							opt_rx->rcv_tsval = ntohl(get_unaligned((__u32 *)ptr));
-							opt_rx->rcv_tsecr = ntohl(get_unaligned((__u32 *)(ptr+4)));
+							opt_rx->rcv_tsval = ntohl(get_unaligned((__be32 *)ptr));
+							opt_rx->rcv_tsecr = ntohl(get_unaligned((__be32 *)(ptr+4)));
 						}
 					}
 					break;
@@ -2695,8 +2695,8 @@
 		return 0;
 	} else if (tp->rx_opt.tstamp_ok &&
 		   th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
-		__u32 *ptr = (__u32 *)(th + 1);
-		if (*ptr == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+		__be32 *ptr = (__be32 *)(th + 1);
+		if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
 				  | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
 			tp->rx_opt.saw_tstamp = 1;
 			++ptr;
@@ -3911,10 +3911,10 @@
 
 		/* Check timestamp */
 		if (tcp_header_len == sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) {
-			__u32 *ptr = (__u32 *)(th + 1);
+			__be32 *ptr = (__be32 *)(th + 1);
 
 			/* No? Slow path! */
-			if (*ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+			if (*ptr != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
 					  | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
 				goto slow_path;
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 39b1798..c83938b 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -159,7 +159,7 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
 	struct rtable *rt;
-	u32 daddr, nexthop;
+	__be32 daddr, nexthop;
 	int tmp;
 	int err;
 
@@ -734,8 +734,8 @@
 	struct inet_request_sock *ireq;
 	struct tcp_options_received tmp_opt;
 	struct request_sock *req;
-	__u32 saddr = skb->nh.iph->saddr;
-	__u32 daddr = skb->nh.iph->daddr;
+	__be32 saddr = skb->nh.iph->saddr;
+	__be32 daddr = skb->nh.iph->daddr;
 	__u32 isn = TCP_SKB_CB(skb)->when;
 	struct dst_entry *dst = NULL;
 #ifdef CONFIG_SYN_COOKIES
@@ -1763,7 +1763,7 @@
 
 static void get_timewait4_sock(struct inet_timewait_sock *tw, char *tmpbuf, int i)
 {
-	unsigned int dest, src;
+	__be32 dest, src;
 	__u16 destp, srcp;
 	int ttd = tw->tw_ttd - jiffies;
 
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
index 308fb7e..f0ebaf0 100644
--- a/net/ipv4/tcp_lp.c
+++ b/net/ipv4/tcp_lp.c
@@ -31,8 +31,6 @@
  *   Hung Hing Lun, Mike <hlhung3i@gmail.com>
  * SourceForge project page:
  *   http://tcp-lp-mod.sourceforge.net/
- *
- * Version: $Id: tcp_lp.c,v 1.24 2006/09/05 20:22:53 hswong3i Exp $
  */
 
 #include <linux/module.h>
@@ -164,7 +162,7 @@
 
  out:
 	/* record time for successful remote HZ calc */
-	if (rhz > 0)
+	if ((rhz >> 6) > 0)
 		lp->flag |= LP_VALID_RHZ;
 	else
 		lp->flag &= ~LP_VALID_RHZ;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 061edfa..9a253fa 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -269,7 +269,7 @@
 	return new_win;
 }
 
-static void tcp_build_and_update_options(__u32 *ptr, struct tcp_sock *tp,
+static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
 					 __u32 tstamp)
 {
 	if (tp->rx_opt.tstamp_ok) {
@@ -305,7 +305,7 @@
  * MAX_SYN_SIZE to match the new maximum number of options that you
  * can generate.
  */
-static void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
+static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack,
 				  int offer_wscale, int wscale, __u32 tstamp,
 				  __u32 ts_recent)
 {
@@ -424,7 +424,7 @@
 	th->dest		= inet->dport;
 	th->seq			= htonl(tcb->seq);
 	th->ack_seq		= htonl(tp->rcv_nxt);
-	*(((__u16 *)th) + 6)	= htons(((tcp_header_size >> 2) << 12) |
+	*(((__be16 *)th) + 6)	= htons(((tcp_header_size >> 2) << 12) |
 					tcb->flags);
 
 	if (unlikely(tcb->flags & TCPCB_FLAG_SYN)) {
@@ -445,7 +445,7 @@
 	}
 
 	if (unlikely(tcb->flags & TCPCB_FLAG_SYN)) {
-		tcp_syn_build_options((__u32 *)(th + 1),
+		tcp_syn_build_options((__be32 *)(th + 1),
 				      tcp_advertise_mss(sk),
 				      (sysctl_flags & SYSCTL_FLAG_TSTAMPS),
 				      (sysctl_flags & SYSCTL_FLAG_SACK),
@@ -454,7 +454,7 @@
 				      tcb->when,
 				      tp->rx_opt.ts_recent);
 	} else {
-		tcp_build_and_update_options((__u32 *)(th + 1),
+		tcp_build_and_update_options((__be32 *)(th + 1),
 					     tp, tcb->when);
 		TCP_ECN_send(sk, tp, skb, tcp_header_size);
 	}
@@ -2070,7 +2070,7 @@
 	th->window = htons(req->rcv_wnd);
 
 	TCP_SKB_CB(skb)->when = tcp_time_stamp;
-	tcp_syn_build_options((__u32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
+	tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
 			      ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
 			      TCP_SKB_CB(skb)->when,
 			      req->ts_recent);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 77e265d..6d6142f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -243,8 +243,8 @@
 /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
  * harder than this. -DaveM
  */
-static struct sock *udp_v4_lookup_longway(u32 saddr, u16 sport,
-					  u32 daddr, u16 dport, int dif)
+static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport,
+					  __be32 daddr, __be16 dport, int dif)
 {
 	struct sock *sk, *result = NULL;
 	struct hlist_node *node;
@@ -288,8 +288,8 @@
 	return result;
 }
 
-static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
-					     u32 daddr, u16 dport, int dif)
+static __inline__ struct sock *udp_v4_lookup(__be32 saddr, __be16 sport,
+					     __be32 daddr, __be16 dport, int dif)
 {
 	struct sock *sk;
 
@@ -302,8 +302,8 @@
 }
 
 static inline struct sock *udp_v4_mcast_next(struct sock *sk,
-					     u16 loc_port, u32 loc_addr,
-					     u16 rmt_port, u32 rmt_addr,
+					     __be16 loc_port, __be32 loc_addr,
+					     __be16 rmt_port, __be32 rmt_addr,
 					     int dif)
 {
 	struct hlist_node *node;
@@ -498,7 +498,7 @@
 }
 
 
-static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
+static unsigned short udp_check(struct udphdr *uh, int len, __be32 saddr, __be32 daddr, unsigned long base)
 {
 	return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
 }
@@ -513,8 +513,8 @@
 	struct rtable *rt = NULL;
 	int free = 0;
 	int connected = 0;
-	u32 daddr, faddr, saddr;
-	u16 dport;
+	__be32 daddr, faddr, saddr;
+	__be16 dport;
 	u8  tos;
 	int err;
 	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
@@ -931,7 +931,7 @@
 	int iphlen, len;
   
 	__u8 *udpdata = (__u8 *)uh + sizeof(struct udphdr);
-	__u32 *udpdata32 = (__u32 *)udpdata;
+	__be32 *udpdata32 = (__be32 *)udpdata;
 	__u16 encap_type = up->encap_type;
 
 	/* if we're overly short, let UDP handle it */
@@ -1080,7 +1080,7 @@
  *	so we don't need to lock the hashes.
  */
 static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
-				 u32 saddr, u32 daddr)
+				 __be32 saddr, __be32 daddr)
 {
 	struct sock *sk;
 	int dif;
@@ -1121,7 +1121,7 @@
  * including udp header and folding it to skb->csum.
  */
 static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
-			     unsigned short ulen, u32 saddr, u32 daddr)
+			     unsigned short ulen, __be32 saddr, __be32 daddr)
 {
 	if (uh->check == 0) {
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1146,8 +1146,8 @@
   	struct udphdr *uh;
 	unsigned short ulen;
 	struct rtable *rt = (struct rtable*)skb->dst;
-	u32 saddr = skb->nh.iph->saddr;
-	u32 daddr = skb->nh.iph->daddr;
+	__be32 saddr = skb->nh.iph->saddr;
+	__be32 daddr = skb->nh.iph->daddr;
 	int len = skb->len;
 
 	/*
@@ -1563,8 +1563,8 @@
 static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
 {
 	struct inet_sock *inet = inet_sk(sp);
-	unsigned int dest = inet->daddr;
-	unsigned int src  = inet->rcv_saddr;
+	__be32 dest = inet->daddr;
+	__be32 src  = inet->rcv_saddr;
 	__u16 destp	  = ntohs(inet->dport);
 	__u16 srcp	  = ntohs(inet->sport);
 
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 040e847..8655d03 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -23,7 +23,7 @@
 
 EXPORT_SYMBOL(xfrm4_rcv);
 
-static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 {
 	switch (nexthdr) {
 	case IPPROTO_IPIP:
@@ -55,7 +55,7 @@
 int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 {
 	int err;
-	u32 spi, seq;
+	__be32 spi, seq;
 	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
 	struct xfrm_state *x;
 	int xfrm_nr = 0;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index eabcd27..7a7a001 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -221,7 +221,7 @@
 
 		case IPPROTO_ESP:
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
-				u32 *ehdr = (u32 *)xprth;
+				__be32 *ehdr = (__be32 *)xprth;
 
 				fl->fl_ipsec_spi = ehdr[0];
 			}
@@ -229,7 +229,7 @@
 
 		case IPPROTO_AH:
 			if (pskb_may_pull(skb, xprth + 8 - skb->data)) {
-				u32 *ah_hdr = (u32*)xprth;
+				__be32 *ah_hdr = (__be32*)xprth;
 
 				fl->fl_ipsec_spi = ah_hdr[1];
 			}
@@ -237,7 +237,7 @@
 
 		case IPPROTO_COMP:
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
-				u16 *ipcomp_hdr = (u16 *)xprth;
+				__be16 *ipcomp_hdr = (__be16 *)xprth;
 
 				fl->fl_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
 			}
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index fe20344..3cc3df0 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -29,9 +29,9 @@
 	x->sel.daddr.a4 = fl->fl4_dst;
 	x->sel.saddr.a4 = fl->fl4_src;
 	x->sel.dport = xfrm_flowi_dport(fl);
-	x->sel.dport_mask = ~0;
+	x->sel.dport_mask = htons(0xffff);
 	x->sel.sport = xfrm_flowi_sport(fl);
-	x->sel.sport_mask = ~0;
+	x->sel.sport_mask = htons(0xffff);
 	x->sel.prefixlen_d = 32;
 	x->sel.prefixlen_s = 32;
 	x->sel.proto = fl->proto;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c186763..e03c33b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1258,8 +1258,8 @@
 {
 	const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
 	const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
-	u32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
-	u32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
+	__be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
+	__be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
 	int sk_ipv6only = ipv6_only_sock(sk);
 	int sk2_ipv6only = inet_v6_ipv6only(sk2);
 	int addr_type = ipv6_addr_type(sk_rcv_saddr6);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index bf6e8af..e94eccb 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -246,7 +246,7 @@
 	struct sock *sk = sock->sk;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
-	__u32 v4addr = 0;
+	__be32 v4addr = 0;
 	unsigned short snum;
 	int addr_type = 0;
 	int err = 0;
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index d2f3fc9..8accd1f 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -64,7 +64,7 @@
 {
 	struct sock *sk;
 	const struct hlist_node *node;
-	const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+	const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
 	/* Optimize here for direct hit, only listening connections can
 	 * have wildcards anyways.
 	 */
@@ -82,7 +82,7 @@
 	sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
 		const struct inet_timewait_sock *tw = inet_twsk(sk);
 
-		if(*((__u32 *)&(tw->tw_dport))	== ports	&&
+		if(*((__portpair *)&(tw->tw_dport))	== ports	&&
 		   sk->sk_family		== PF_INET6) {
 			const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
 
@@ -171,7 +171,7 @@
 	const struct in6_addr *daddr = &np->rcv_saddr;
 	const struct in6_addr *saddr = &np->daddr;
 	const int dif = sk->sk_bound_dev_if;
-	const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+	const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
 	const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr,
 						inet->dport);
 	struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
@@ -188,7 +188,7 @@
 
 		tw = inet_twsk(sk2);
 
-		if(*((__u32 *)&(tw->tw_dport)) == ports		 &&
+		if(*((__portpair *)&(tw->tw_dport)) == ports		 &&
 		   sk2->sk_family	       == PF_INET6	 &&
 		   ipv6_addr_equal(&tw6->tw_v6_daddr, saddr)	 &&
 		   ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index ad9c6e8..a2860e3 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -178,7 +178,7 @@
 static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 		                int type, int code, int offset, __u32 info)
 {
-	u32 spi;
+	__be32 spi;
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 	struct ipv6_comp_hdr *ipcomph = (struct ipv6_comp_hdr*)(skb->data+offset);
 	struct xfrm_state *x;
@@ -234,7 +234,7 @@
 {
 	int err = 0;
 	struct xfrm_state *t = NULL;
-	u32 spi;
+	__be32 spi;
 
 	spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr);
 	if (spi)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 4f3bb7f..de6b919 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -123,6 +123,9 @@
 	struct ipv6hdr *ipv6h;
 	struct inet6_protocol *ops;
 
+	if (!(features & NETIF_F_HW_CSUM))
+		features &= ~NETIF_F_SG;
+
 	if (unlikely(skb_shinfo(skb)->gso_type &
 		     ~(SKB_GSO_UDP |
 		       SKB_GSO_DODGY |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 2546fc9..3b65754 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1237,7 +1237,7 @@
 
 	skb->dev = NULL;
 
-	bh_lock_sock(sk);
+	bh_lock_sock_nested(sk);
 	ret = 0;
 	if (!sock_owned_by_user(sk)) {
 #ifdef CONFIG_NET_DMA
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index a40a057..5c8b7a5 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -16,10 +16,10 @@
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
+int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
 {
 	int err;
-	u32 seq;
+	__be32 seq;
 	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
 	struct xfrm_state *x;
 	int xfrm_nr = 0;
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index 711bfaf..9ddaa9d 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -29,9 +29,9 @@
 	ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
 	ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
 	x->sel.dport = xfrm_flowi_dport(fl);
-	x->sel.dport_mask = ~0;
+	x->sel.dport_mask = htons(0xffff);
 	x->sel.sport = xfrm_flowi_sport(fl);
-	x->sel.sport_mask = ~0;
+	x->sel.sport_mask = htons(0xffff);
 	x->sel.prefixlen_d = 128;
 	x->sel.prefixlen_s = 128;
 	x->sel.proto = fl->proto;
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 59685ee..7af227b 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -258,7 +258,7 @@
 static int xfrm6_tunnel_rcv(struct sk_buff *skb)
 {
 	struct ipv6hdr *iph = skb->nh.ipv6h;
-	u32 spi;
+	__be32 spi;
 
 	spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
 	return xfrm6_rcv_spi(skb, spi);
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 17699ee..7e1aea8 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -132,13 +132,14 @@
 
 	/* Prevent race conditions with irda_release() and irda_shutdown() */
 	if (!sock_flag(sk, SOCK_DEAD) && sk->sk_state != TCP_CLOSE) {
+		lock_sock(sk);
 		sk->sk_state     = TCP_CLOSE;
 		sk->sk_err       = ECONNRESET;
 		sk->sk_shutdown |= SEND_SHUTDOWN;
 
 		sk->sk_state_change(sk);
-		/* Uh-oh... Should use sock_orphan ? */
-                sock_set_flag(sk, SOCK_DEAD);
+                sock_orphan(sk);
+		release_sock(sk);
 
 		/* Close our TSAP.
 		 * If we leave it open, IrLMP put it back into the list of
@@ -308,7 +309,8 @@
 
 	IRDA_ASSERT(self != NULL, return;);
 
-	skb = alloc_skb(64, GFP_ATOMIC);
+	skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+			GFP_ATOMIC);
 	if (skb == NULL) {
 		IRDA_DEBUG(0, "%s() Unable to allocate sk_buff!\n",
 			   __FUNCTION__);
@@ -1212,6 +1214,7 @@
         if (sk == NULL)
 		return 0;
 
+	lock_sock(sk);
 	sk->sk_state       = TCP_CLOSE;
 	sk->sk_shutdown   |= SEND_SHUTDOWN;
 	sk->sk_state_change(sk);
@@ -1221,6 +1224,7 @@
 
 	sock_orphan(sk);
 	sock->sk   = NULL;
+	release_sock(sk);
 
 	/* Purge queues (see sock_init_data()) */
 	skb_queue_purge(&sk->sk_receive_queue);
@@ -1353,6 +1357,7 @@
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	IRDA_ASSERT(self != NULL, return -1;);
+	IRDA_ASSERT(!sock_error(sk), return -1;);
 
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 				flags & MSG_DONTWAIT, &err);
@@ -1405,6 +1410,7 @@
 	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
 	IRDA_ASSERT(self != NULL, return -1;);
+	IRDA_ASSERT(!sock_error(sk), return -1;);
 
 	if (sock->flags & __SO_ACCEPTCON)
 		return(-EINVAL);
diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
index 959874b..c8e0d89 100644
--- a/net/irda/ircomm/ircomm_lmp.c
+++ b/net/irda/ircomm/ircomm_lmp.c
@@ -81,7 +81,7 @@
 	
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
-		tx_skb = alloc_skb(64, GFP_ATOMIC);
+		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 		if (!tx_skb)
 			return -ENOMEM;
 
@@ -115,7 +115,7 @@
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
 
         if (!userdata) {
-		tx_skb = alloc_skb(64, GFP_ATOMIC);
+		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 		if (!tx_skb)
 			return -ENOMEM;
 		
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 61128aa..415cf4e 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -345,10 +345,11 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 
-	tx_skb = alloc_skb(64, GFP_ATOMIC);
+	tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 	if (tx_skb == NULL) {
-		IRDA_DEBUG(0, "%s(), Could not allocate an sk_buff of length %d\n", 
-			__FUNCTION__, 64);
+		IRDA_DEBUG(0,
+			   "%s(), Could not allocate an sk_buff of length %d\n",
+			   __FUNCTION__, LMP_MAX_HEADER);
 		return;
 	}
 
@@ -701,7 +702,7 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 
-	tx_skb = alloc_skb(64, GFP_ATOMIC);
+	tx_skb = alloc_skb(LMP_MAX_HEADER + 1, GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c
index da17395..99b18dc 100644
--- a/net/irda/iriap_event.c
+++ b/net/irda/iriap_event.c
@@ -365,7 +365,7 @@
 
 	switch (event) {
 	case IAP_LM_CONNECT_INDICATION:
-		tx_skb = alloc_skb(64, GFP_ATOMIC);
+		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 		if (tx_skb == NULL) {
 			IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
 			return;
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index 7dd0a2f..9b962f2 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -636,7 +636,8 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	skb = alloc_skb(64, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER,
+			GFP_ATOMIC);
 	if (!skb)
 		return;
 
@@ -668,7 +669,10 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb = alloc_skb(64, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3") +
+			IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "DIRECT"),
+			GFP_ATOMIC);
 	if (!skb)
 		return;
 
@@ -704,7 +708,9 @@
 	if (self->client.tsap_ctrl == NULL)
 		return;
 
-	skb = alloc_skb(64, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN"),
+			GFP_ATOMIC);
 	if (!skb)
 		return;
 
@@ -715,7 +721,7 @@
 	
 	/* Build frame */
  	frame[0] = CMD_CLOSE_DATA_CHAN;
-	frame[1] = 0x01; /* Two parameters */
+	frame[1] = 0x01; /* One parameter */
 
 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
 
@@ -739,7 +745,11 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	
 	
-	skb = alloc_skb(128, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
+			GFP_ATOMIC);
 	if (!skb)
 		return;
 
@@ -777,7 +787,12 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
- 	skb = alloc_skb(128, GFP_ATOMIC);
+ 	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BROADCAST") +
+			/* We may waste one byte here...*/
+			IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
+			GFP_ATOMIC);
 	if (!skb)
 		return;
 
@@ -816,7 +831,12 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
- 	skb = alloc_skb(128, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") +
+			/* We may waste one byte here...*/
+			IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "NONE"),
+			GFP_ATOMIC);
 	if (!skb)
 		return;
 	
@@ -856,7 +876,12 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb = alloc_skb(128, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_OPERATION",
+						   "DYNAMIC"),
+			GFP_ATOMIC);
 	if (!skb)
 		return;
 
@@ -891,7 +916,10 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb = alloc_skb(64, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3"),
+			GFP_ATOMIC);
+
 	if (!skb)
 		return;
 
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index 9c0df86..58efde9 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -296,7 +296,14 @@
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	skb = alloc_skb(128, GFP_ATOMIC);
+	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+			/* Bigger param length comes from CMD_GET_MEDIA_CHAR */
+			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BORADCAST") +
+			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") +
+			IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "HOSTED"),
+			GFP_ATOMIC);
+
 	if (!skb)
 		return;
 
@@ -354,8 +361,7 @@
 		} else
 			skb->data[1] = 0x02; /* 2 parameters */
 		irlan_insert_byte_param(skb, "DATA_CHAN", self->stsap_sel_data);
-		irlan_insert_array_param(skb, "RECONNECT_KEY", "LINUX RULES!",
-					 12);
+		irlan_insert_string_param(skb, "RECONNECT_KEY", "LINUX RULES!");
 		break;
 	case CMD_FILTER_OPERATION:
 		irlan_filter_request(self, skb);
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index ccb983b..dba349c 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -117,7 +117,9 @@
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Allocate frame */
-	tx_skb = alloc_skb(64, GFP_ATOMIC);
+	tx_skb = alloc_skb(sizeof(struct snrm_frame) +
+			   IRLAP_NEGOCIATION_PARAMS_LEN,
+			   GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
@@ -136,7 +138,7 @@
 	 *  If we are establishing a connection then insert QoS paramerters
 	 */
 	if (qos) {
-		skb_put(tx_skb, 9); /* 21 left */
+		skb_put(tx_skb, 9); /* 25 left */
 		frame->saddr = cpu_to_le32(self->saddr);
 		frame->daddr = cpu_to_le32(self->daddr);
 
@@ -210,7 +212,9 @@
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Allocate frame */
-	tx_skb = alloc_skb(64, GFP_ATOMIC);
+	tx_skb = alloc_skb(sizeof(struct ua_frame) +
+			   IRLAP_NEGOCIATION_PARAMS_LEN,
+			   GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
@@ -245,23 +249,23 @@
 void irlap_send_dm_frame( struct irlap_cb *self)
 {
 	struct sk_buff *tx_skb = NULL;
-	__u8 *frame;
+	struct dm_frame *frame;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
-	tx_skb = alloc_skb(32, GFP_ATOMIC);
+	tx_skb = alloc_skb(sizeof(struct dm_frame), GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
-	frame = skb_put(tx_skb, 2);
+	frame = (struct dm_frame *)skb_put(tx_skb, 2);
 
 	if (self->state == LAP_NDM)
-		frame[0] = CBROADCAST;
+		frame->caddr = CBROADCAST;
 	else
-		frame[0] = self->caddr;
+		frame->caddr = self->caddr;
 
-	frame[1] = DM_RSP | PF_BIT;
+	frame->control = DM_RSP | PF_BIT;
 
 	irlap_queue_xmit(self, tx_skb);
 }
@@ -275,21 +279,21 @@
 void irlap_send_disc_frame(struct irlap_cb *self)
 {
 	struct sk_buff *tx_skb = NULL;
-	__u8 *frame;
+	struct disc_frame *frame;
 
 	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
-	tx_skb = alloc_skb(16, GFP_ATOMIC);
+	tx_skb = alloc_skb(sizeof(struct disc_frame), GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
-	frame = skb_put(tx_skb, 2);
+	frame = (struct disc_frame *)skb_put(tx_skb, 2);
 
-	frame[0] = self->caddr | CMD_FRAME;
-	frame[1] = DISC_CMD | PF_BIT;
+	frame->caddr = self->caddr | CMD_FRAME;
+	frame->control = DISC_CMD | PF_BIT;
 
 	irlap_queue_xmit(self, tx_skb);
 }
@@ -315,7 +319,8 @@
 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 	IRDA_ASSERT(discovery != NULL, return;);
 
-	tx_skb = alloc_skb(64, GFP_ATOMIC);
+	tx_skb = alloc_skb(sizeof(struct xid_frame) + IRLAP_DISCOVERY_INFO_LEN,
+			   GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
@@ -573,18 +578,18 @@
 void irlap_send_rr_frame(struct irlap_cb *self, int command)
 {
 	struct sk_buff *tx_skb;
-	__u8 *frame;
+	struct rr_frame *frame;
 
-	tx_skb = alloc_skb(16, GFP_ATOMIC);
+	tx_skb = alloc_skb(sizeof(struct rr_frame), GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
-	frame = skb_put(tx_skb, 2);
+	frame = (struct rr_frame *)skb_put(tx_skb, 2);
 
-	frame[0] = self->caddr;
-	frame[0] |= (command) ? CMD_FRAME : 0;
+	frame->caddr = self->caddr;
+	frame->caddr |= (command) ? CMD_FRAME : 0;
 
-	frame[1] = RR | PF_BIT | (self->vr << 5);
+	frame->control = RR | PF_BIT | (self->vr << 5);
 
 	irlap_queue_xmit(self, tx_skb);
 }
@@ -598,16 +603,16 @@
 void irlap_send_rd_frame(struct irlap_cb *self)
 {
 	struct sk_buff *tx_skb;
-	__u8 *frame;
+	struct rd_frame *frame;
 
-	tx_skb = alloc_skb(16, GFP_ATOMIC);
+	tx_skb = alloc_skb(sizeof(struct rd_frame), GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
-	frame = skb_put(tx_skb, 2);
+	frame = (struct rd_frame *)skb_put(tx_skb, 2);
 
-	frame[0] = self->caddr;
-	frame[1] = RD_RSP | PF_BIT;
+	frame->caddr = self->caddr;
+	frame->caddr = RD_RSP | PF_BIT;
 
 	irlap_queue_xmit(self, tx_skb);
 }
@@ -1214,7 +1219,7 @@
 	struct test_frame *frame;
 	__u8 *info;
 
-	tx_skb = alloc_skb(cmd->len+sizeof(struct test_frame), GFP_ATOMIC);
+	tx_skb = alloc_skb(cmd->len + sizeof(struct test_frame), GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index c440913..5073261 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -392,7 +392,7 @@
 
 	/* Any userdata? */
 	if (tx_skb == NULL) {
-		tx_skb = alloc_skb(64, GFP_ATOMIC);
+		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 		if (!tx_skb)
 			return -ENOMEM;
 
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 42acf1c..3c2e70b 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -804,12 +804,12 @@
 		   self->send_credit, self->avail_credit, self->remote_credit);
 
 	/* Give credit to peer */
-	tx_skb = alloc_skb(64, GFP_ATOMIC);
+	tx_skb = alloc_skb(TTP_MAX_HEADER, GFP_ATOMIC);
 	if (!tx_skb)
 		return;
 
 	/* Reserve space for LMP, and LAP header */
-	skb_reserve(tx_skb, self->max_header_size);
+	skb_reserve(tx_skb, LMP_MAX_HEADER);
 
 	/*
 	 *  Since we can transmit and receive frames concurrently,
@@ -1093,7 +1093,8 @@
 
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
-		tx_skb = alloc_skb(64, GFP_ATOMIC);
+		tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+				   GFP_ATOMIC);
 		if (!tx_skb)
 			return -ENOMEM;
 
@@ -1341,7 +1342,8 @@
 
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
-		tx_skb = alloc_skb(64, GFP_ATOMIC);
+		tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+				   GFP_ATOMIC);
 		if (!tx_skb)
 			return -ENOMEM;
 
@@ -1540,14 +1542,14 @@
 
 	if (!userdata) {
 		struct sk_buff *tx_skb;
-		tx_skb = alloc_skb(64, GFP_ATOMIC);
+		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 		if (!tx_skb)
 			return -ENOMEM;
 
 		/*
 		 *  Reserve space for MUX and LAP header
 		 */
-		skb_reserve(tx_skb, TTP_MAX_HEADER);
+		skb_reserve(tx_skb, LMP_MAX_HEADER);
 
 		userdata = tx_skb;
 	}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 83b443d..ff98e70 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2140,7 +2140,7 @@
 	xp->selector.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
 	xp->selector.sport = ((struct sockaddr_in *)(sa+1))->sin_port;
 	if (xp->selector.sport)
-		xp->selector.sport_mask = ~0;
+		xp->selector.sport_mask = htons(0xffff);
 
 	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], 
 	pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);
@@ -2153,7 +2153,7 @@
 
 	xp->selector.dport = ((struct sockaddr_in *)(sa+1))->sin_port;
 	if (xp->selector.dport)
-		xp->selector.dport_mask = ~0;
+		xp->selector.dport_mask = htons(0xffff);
 
 	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
 	if (sec_ctx != NULL) {
@@ -2243,7 +2243,7 @@
 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
 	sel.sport = ((struct sockaddr_in *)(sa+1))->sin_port;
 	if (sel.sport)
-		sel.sport_mask = ~0;
+		sel.sport_mask = htons(0xffff);
 
 	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], 
 	pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
@@ -2251,7 +2251,7 @@
 	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
 	sel.dport = ((struct sockaddr_in *)(sa+1))->sin_port;
 	if (sel.dport)
-		sel.dport_mask = ~0;
+		sel.dport_mask = htons(0xffff);
 
 	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
 	memset(&tmp, 0, sizeof(struct xfrm_policy));
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 4125a55..09986ca 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -32,6 +32,7 @@
 #include <linux/socket.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
+#include <linux/audit.h>
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
@@ -162,8 +163,7 @@
 	int nla_a_rem;
 	int nla_b_rem;
 
-	if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
-	    !info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
+	if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
 	    !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
 		return -EINVAL;
 
@@ -344,8 +344,7 @@
 	int ret_val;
 	struct cipso_v4_doi *doi_def = NULL;
 
-	if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
-	    !info->attrs[NLBL_CIPSOV4_A_TAGLST])
+	if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
 		return -EINVAL;
 
 	doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
@@ -381,21 +380,35 @@
 
 {
 	int ret_val = -EINVAL;
-	u32 map_type;
+	u32 type;
+	u32 doi;
+	const char *type_str = "(unknown)";
+	struct audit_buffer *audit_buf;
 
-	if (!info->attrs[NLBL_CIPSOV4_A_MTYPE])
+	if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
+	    !info->attrs[NLBL_CIPSOV4_A_MTYPE])
 		return -EINVAL;
 
-	map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
-	switch (map_type) {
+	type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
+	switch (type) {
 	case CIPSO_V4_MAP_STD:
+		type_str = "std";
 		ret_val = netlbl_cipsov4_add_std(info);
 		break;
 	case CIPSO_V4_MAP_PASS:
+		type_str = "pass";
 		ret_val = netlbl_cipsov4_add_pass(info);
 		break;
 	}
 
+	if (ret_val == 0) {
+		doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
+		audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
+						      NETLINK_CB(skb).sid);
+		audit_log_format(audit_buf, " doi=%u type=%s", doi, type_str);
+		audit_log_end(audit_buf);
+	}
+
 	return ret_val;
 }
 
@@ -653,11 +666,21 @@
 static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
 {
 	int ret_val = -EINVAL;
-	u32 doi;
+	u32 doi = 0;
+	struct audit_buffer *audit_buf;
 
 	if (info->attrs[NLBL_CIPSOV4_A_DOI]) {
 		doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
-		ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
+		ret_val = cipso_v4_doi_remove(doi,
+					      NETLINK_CB(skb).sid,
+					      netlbl_cipsov4_doi_free);
+	}
+
+	if (ret_val == 0) {
+		audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
+						      NETLINK_CB(skb).sid);
+		audit_log_format(audit_buf, " doi=%u", doi);
+		audit_log_end(audit_buf);
 	}
 
 	return ret_val;
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index f56d7a8..d64e2ae 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -35,12 +35,14 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
+#include <linux/audit.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
 #include <asm/bug.h>
 
 #include "netlabel_mgmt.h"
 #include "netlabel_domainhash.h"
+#include "netlabel_user.h"
 
 struct netlbl_domhsh_tbl {
 	struct list_head *tbl;
@@ -186,6 +188,7 @@
 /**
  * netlbl_domhsh_add - Adds a entry to the domain hash table
  * @entry: the entry to add
+ * @audit_secid: the LSM secid to use in the audit message
  *
  * Description:
  * Adds a new entry to the domain hash table and handles any updates to the
@@ -193,10 +196,12 @@
  * negative on failure.
  *
  */
-int netlbl_domhsh_add(struct netlbl_dom_map *entry)
+int netlbl_domhsh_add(struct netlbl_dom_map *entry, u32 audit_secid)
 {
 	int ret_val;
 	u32 bkt;
+	struct audit_buffer *audit_buf;
+	char *audit_domain;
 
 	switch (entry->type) {
 	case NETLBL_NLTYPE_UNLABELED:
@@ -236,6 +241,26 @@
 		spin_unlock(&netlbl_domhsh_def_lock);
 	} else
 		ret_val = -EINVAL;
+	if (ret_val == 0) {
+		if (entry->domain != NULL)
+			audit_domain = entry->domain;
+		else
+			audit_domain = "(default)";
+		audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD,
+						      audit_secid);
+		audit_log_format(audit_buf, " domain=%s", audit_domain);
+		switch (entry->type) {
+		case NETLBL_NLTYPE_UNLABELED:
+			audit_log_format(audit_buf, " protocol=unlbl");
+			break;
+		case NETLBL_NLTYPE_CIPSOV4:
+			audit_log_format(audit_buf,
+					 " protocol=cipsov4 doi=%u",
+					 entry->type_def.cipsov4->doi);
+			break;
+		}
+		audit_log_end(audit_buf);
+	}
 	rcu_read_unlock();
 
 	if (ret_val != 0) {
@@ -254,6 +279,7 @@
 /**
  * netlbl_domhsh_add_default - Adds the default entry to the domain hash table
  * @entry: the entry to add
+ * @audit_secid: the LSM secid to use in the audit message
  *
  * Description:
  * Adds a new default entry to the domain hash table and handles any updates
@@ -261,14 +287,15 @@
  * negative on failure.
  *
  */
-int netlbl_domhsh_add_default(struct netlbl_dom_map *entry)
+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry, u32 audit_secid)
 {
-	return netlbl_domhsh_add(entry);
+	return netlbl_domhsh_add(entry, audit_secid);
 }
 
 /**
  * netlbl_domhsh_remove - Removes an entry from the domain hash table
  * @domain: the domain to remove
+ * @audit_secid: the LSM secid to use in the audit message
  *
  * Description:
  * Removes an entry from the domain hash table and handles any updates to the
@@ -276,10 +303,12 @@
  * negative on failure.
  *
  */
-int netlbl_domhsh_remove(const char *domain)
+int netlbl_domhsh_remove(const char *domain, u32 audit_secid)
 {
 	int ret_val = -ENOENT;
 	struct netlbl_dom_map *entry;
+	struct audit_buffer *audit_buf;
+	char *audit_domain;
 
 	rcu_read_lock();
 	if (domain != NULL)
@@ -316,8 +345,18 @@
 			ret_val = -ENOENT;
 		spin_unlock(&netlbl_domhsh_def_lock);
 	}
-	if (ret_val == 0)
+	if (ret_val == 0) {
+		if (entry->domain != NULL)
+			audit_domain = entry->domain;
+		else
+			audit_domain = "(default)";
+		audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL,
+						      audit_secid);
+		audit_log_format(audit_buf, " domain=%s", audit_domain);
+		audit_log_end(audit_buf);
+
 		call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
+	}
 
 remove_return:
 	rcu_read_unlock();
@@ -326,6 +365,7 @@
 
 /**
  * netlbl_domhsh_remove_default - Removes the default entry from the table
+ * @audit_secid: the LSM secid to use in the audit message
  *
  * Description:
  * Removes/resets the default entry for the domain hash table and handles any
@@ -333,9 +373,9 @@
  * success, non-zero on failure.
  *
  */
-int netlbl_domhsh_remove_default(void)
+int netlbl_domhsh_remove_default(u32 audit_secid)
 {
-	return netlbl_domhsh_remove(NULL);
+	return netlbl_domhsh_remove(NULL, audit_secid);
 }
 
 /**
diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h
index 02af72a..d50f13c 100644
--- a/net/netlabel/netlabel_domainhash.h
+++ b/net/netlabel/netlabel_domainhash.h
@@ -57,9 +57,9 @@
 int netlbl_domhsh_init(u32 size);
 
 /* Manipulate the domain hash table */
-int netlbl_domhsh_add(struct netlbl_dom_map *entry);
-int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
-int netlbl_domhsh_remove_default(void);
+int netlbl_domhsh_add(struct netlbl_dom_map *entry, u32 audit_secid);
+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry, u32 audit_secid);
+int netlbl_domhsh_remove_default(u32 audit_secid);
 struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
 int netlbl_domhsh_walk(u32 *skip_bkt,
 		     u32 *skip_chain,
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 8626c9f..0ac314f 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -108,7 +108,7 @@
 
 	switch (entry->type) {
 	case NETLBL_NLTYPE_UNLABELED:
-		ret_val = netlbl_domhsh_add(entry);
+		ret_val = netlbl_domhsh_add(entry, NETLINK_CB(skb).sid);
 		break;
 	case NETLBL_NLTYPE_CIPSOV4:
 		if (!info->attrs[NLBL_MGMT_A_CV4DOI])
@@ -125,7 +125,7 @@
 			rcu_read_unlock();
 			goto add_failure;
 		}
-		ret_val = netlbl_domhsh_add(entry);
+		ret_val = netlbl_domhsh_add(entry, NETLINK_CB(skb).sid);
 		rcu_read_unlock();
 		break;
 	default:
@@ -161,7 +161,7 @@
 		return -EINVAL;
 
 	domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
-	return netlbl_domhsh_remove(domain);
+	return netlbl_domhsh_remove(domain, NETLINK_CB(skb).sid);
 }
 
 /**
@@ -277,7 +277,8 @@
 
 	switch (entry->type) {
 	case NETLBL_NLTYPE_UNLABELED:
-		ret_val = netlbl_domhsh_add_default(entry);
+		ret_val = netlbl_domhsh_add_default(entry,
+						    NETLINK_CB(skb).sid);
 		break;
 	case NETLBL_NLTYPE_CIPSOV4:
 		if (!info->attrs[NLBL_MGMT_A_CV4DOI])
@@ -294,7 +295,8 @@
 			rcu_read_unlock();
 			goto adddef_failure;
 		}
-		ret_val = netlbl_domhsh_add_default(entry);
+		ret_val = netlbl_domhsh_add_default(entry,
+						    NETLINK_CB(skb).sid);
 		rcu_read_unlock();
 		break;
 	default:
@@ -322,7 +324,7 @@
  */
 static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
 {
-	return netlbl_domhsh_remove_default();
+	return netlbl_domhsh_remove_default(NETLINK_CB(skb).sid);
 }
 
 /**
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 440f5c4..ab36675 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -64,6 +64,27 @@
 };
 
 /*
+ * Helper Functions
+ */
+
+/**
+ * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
+ * @value: desired value
+ * @audit_secid: the LSM secid to use in the audit message
+ *
+ * Description:
+ * Set the value of the unlabeled accept flag to @value.
+ *
+ */
+static void netlbl_unlabel_acceptflg_set(u8 value, u32 audit_secid)
+{
+	atomic_set(&netlabel_unlabel_accept_flg, value);
+	netlbl_audit_nomsg((value ?
+			    AUDIT_MAC_UNLBL_ACCEPT : AUDIT_MAC_UNLBL_DENY),
+			   audit_secid);
+}
+
+/*
  * NetLabel Command Handlers
  */
 
@@ -79,18 +100,18 @@
  */
 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
 {
-	int ret_val = -EINVAL;
 	u8 value;
 
 	if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
 		value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
 		if (value == 1 || value == 0) {
-			atomic_set(&netlabel_unlabel_accept_flg, value);
-			ret_val = 0;
+			netlbl_unlabel_acceptflg_set(value,
+						     NETLINK_CB(skb).sid);
+			return 0;
 		}
 	}
 
-	return ret_val;
+	return -EINVAL;
 }
 
 /**
@@ -229,16 +250,19 @@
 {
 	int ret_val;
 	struct netlbl_dom_map *entry;
+	u32 secid;
+
+	security_task_getsecid(current, &secid);
 
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (entry == NULL)
 		return -ENOMEM;
 	entry->type = NETLBL_NLTYPE_UNLABELED;
-	ret_val = netlbl_domhsh_add_default(entry);
+	ret_val = netlbl_domhsh_add_default(entry, secid);
 	if (ret_val != 0)
 		return ret_val;
 
-	atomic_set(&netlabel_unlabel_accept_flg, 1);
+	netlbl_unlabel_acceptflg_set(1, secid);
 
 	return 0;
 }
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index eeb7d76..c2343af 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -32,6 +32,9 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/socket.h>
+#include <linux/audit.h>
+#include <linux/tty.h>
+#include <linux/security.h>
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
@@ -74,3 +77,91 @@
 
 	return 0;
 }
+
+/*
+ * NetLabel Audit Functions
+ */
+
+/**
+ * netlbl_audit_start_common - Start an audit message
+ * @type: audit message type
+ * @secid: LSM context ID
+ *
+ * Description:
+ * Start an audit message using the type specified in @type and fill the audit
+ * message with some fields common to all NetLabel audit messages.  Returns
+ * a pointer to the audit buffer on success, NULL on failure.
+ *
+ */
+struct audit_buffer *netlbl_audit_start_common(int type, u32 secid)
+{
+	struct audit_context *audit_ctx = current->audit_context;
+	struct audit_buffer *audit_buf;
+	uid_t audit_loginuid;
+	const char *audit_tty;
+	char audit_comm[sizeof(current->comm)];
+	struct vm_area_struct *vma;
+	char *secctx;
+	u32 secctx_len;
+
+	audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type);
+	if (audit_buf == NULL)
+		return NULL;
+
+	audit_loginuid = audit_get_loginuid(audit_ctx);
+	if (current->signal &&
+	    current->signal->tty &&
+	    current->signal->tty->name)
+		audit_tty = current->signal->tty->name;
+	else
+		audit_tty = "(none)";
+	get_task_comm(audit_comm, current);
+
+	audit_log_format(audit_buf,
+			 "netlabel: auid=%u uid=%u tty=%s pid=%d",
+			 audit_loginuid,
+			 current->uid,
+			 audit_tty,
+			 current->pid);
+	audit_log_format(audit_buf, " comm=");
+	audit_log_untrustedstring(audit_buf, audit_comm);
+	if (current->mm) {
+		down_read(&current->mm->mmap_sem);
+		vma = current->mm->mmap;
+		while (vma) {
+			if ((vma->vm_flags & VM_EXECUTABLE) &&
+			    vma->vm_file) {
+				audit_log_d_path(audit_buf,
+						 " exe=",
+						 vma->vm_file->f_dentry,
+						 vma->vm_file->f_vfsmnt);
+				break;
+			}
+			vma = vma->vm_next;
+		}
+		up_read(&current->mm->mmap_sem);
+	}
+
+	if (secid != 0 &&
+	    security_secid_to_secctx(secid, &secctx, &secctx_len) == 0)
+		audit_log_format(audit_buf, " subj=%s", secctx);
+
+	return audit_buf;
+}
+
+/**
+ * netlbl_audit_nomsg - Send an audit message without additional text
+ * @type: audit message type
+ * @secid: LSM context ID
+ *
+ * Description:
+ * Send an audit message with only the common NetLabel audit fields.
+ *
+ */
+void netlbl_audit_nomsg(int type, u32 secid)
+{
+	struct audit_buffer *audit_buf;
+
+	audit_buf = netlbl_audit_start_common(type, secid);
+	audit_log_end(audit_buf);
+}
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
index 3f9386b..ab840ac 100644
--- a/net/netlabel/netlabel_user.h
+++ b/net/netlabel/netlabel_user.h
@@ -34,6 +34,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 #include <linux/capability.h>
+#include <linux/audit.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 #include <net/netlabel.h>
@@ -75,4 +76,9 @@
 
 int netlbl_netlink_init(void);
 
+/* NetLabel Audit Functions */
+
+struct audit_buffer *netlbl_audit_start_common(int type, u32 secid);
+void netlbl_audit_nomsg(int type, u32 secid);
+
 #endif
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 7e14f14..37a1840 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -401,7 +401,7 @@
 	if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
 		return skb->len;
 
-	read_lock_bh(&qdisc_tree_lock);
+	read_lock(&qdisc_tree_lock);
 	if (!tcm->tcm_parent)
 		q = dev->qdisc_sleeping;
 	else
@@ -458,7 +458,7 @@
 	if (cl)
 		cops->put(q, cl);
 out:
-	read_unlock_bh(&qdisc_tree_lock);
+	read_unlock(&qdisc_tree_lock);
 	dev_put(dev);
 	return skb->len;
 }
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 86cac49..09fda68 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -194,7 +194,7 @@
 	if (handle)
 		f->handle = handle;
 	else {
-		int i = 0x80000000;
+		unsigned int i = 0x80000000;
 		do {
 			if (++head->hgenerator == 0x7FFFFFFF)
 				head->hgenerator = 1;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index a19eff1..0b64892 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -195,14 +195,14 @@
 {
 	struct Qdisc *q;
 
-	read_lock_bh(&qdisc_tree_lock);
+	read_lock(&qdisc_tree_lock);
 	list_for_each_entry(q, &dev->qdisc_list, list) {
 		if (q->handle == handle) {
-			read_unlock_bh(&qdisc_tree_lock);
+			read_unlock(&qdisc_tree_lock);
 			return q;
 		}
 	}
-	read_unlock_bh(&qdisc_tree_lock);
+	read_unlock(&qdisc_tree_lock);
 	return NULL;
 }
 
@@ -837,7 +837,7 @@
 			continue;
 		if (idx > s_idx)
 			s_q_idx = 0;
-		read_lock_bh(&qdisc_tree_lock);
+		read_lock(&qdisc_tree_lock);
 		q_idx = 0;
 		list_for_each_entry(q, &dev->qdisc_list, list) {
 			if (q_idx < s_q_idx) {
@@ -846,12 +846,12 @@
 			}
 			if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
 					  cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
-				read_unlock_bh(&qdisc_tree_lock);
+				read_unlock(&qdisc_tree_lock);
 				goto done;
 			}
 			q_idx++;
 		}
-		read_unlock_bh(&qdisc_tree_lock);
+		read_unlock(&qdisc_tree_lock);
 	}
 
 done:
@@ -1074,7 +1074,7 @@
 	s_t = cb->args[0];
 	t = 0;
 
-	read_lock_bh(&qdisc_tree_lock);
+	read_lock(&qdisc_tree_lock);
 	list_for_each_entry(q, &dev->qdisc_list, list) {
 		if (t < s_t || !q->ops->cl_ops ||
 		    (tcm->tcm_parent &&
@@ -1096,7 +1096,7 @@
 			break;
 		t++;
 	}
-	read_unlock_bh(&qdisc_tree_lock);
+	read_unlock(&qdisc_tree_lock);
 
 	cb->args[0] = t;
 
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 6f91518..88c6a99 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -45,11 +45,10 @@
    The idea is the following:
    - enqueue, dequeue are serialized via top level device
      spinlock dev->queue_lock.
-   - tree walking is protected by read_lock_bh(qdisc_tree_lock)
+   - tree walking is protected by read_lock(qdisc_tree_lock)
      and this lock is used only in process context.
-   - updates to tree are made under rtnl semaphore or
-     from softirq context (__qdisc_destroy rcu-callback)
-     hence this lock needs local bh disabling.
+   - updates to tree are made only under rtnl semaphore,
+     hence this lock may be made without local bh disabling.
 
    qdisc_tree_lock must be grabbed BEFORE dev->queue_lock!
  */
@@ -57,14 +56,14 @@
 
 void qdisc_lock_tree(struct net_device *dev)
 {
-	write_lock_bh(&qdisc_tree_lock);
+	write_lock(&qdisc_tree_lock);
 	spin_lock_bh(&dev->queue_lock);
 }
 
 void qdisc_unlock_tree(struct net_device *dev)
 {
 	spin_unlock_bh(&dev->queue_lock);
-	write_unlock_bh(&qdisc_tree_lock);
+	write_unlock(&qdisc_tree_lock);
 }
 
 /* 
@@ -483,20 +482,6 @@
 static void __qdisc_destroy(struct rcu_head *head)
 {
 	struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu);
-	struct Qdisc_ops  *ops = qdisc->ops;
-
-#ifdef CONFIG_NET_ESTIMATOR
-	gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
-#endif
-	write_lock(&qdisc_tree_lock);
-	if (ops->reset)
-		ops->reset(qdisc);
-	if (ops->destroy)
-		ops->destroy(qdisc);
-	write_unlock(&qdisc_tree_lock);
-	module_put(ops->owner);
-
-	dev_put(qdisc->dev);
 	kfree((char *) qdisc - qdisc->padded);
 }
 
@@ -504,32 +489,23 @@
 
 void qdisc_destroy(struct Qdisc *qdisc)
 {
-	struct list_head cql = LIST_HEAD_INIT(cql);
-	struct Qdisc *cq, *q, *n;
+	struct Qdisc_ops  *ops = qdisc->ops;
 
 	if (qdisc->flags & TCQ_F_BUILTIN ||
-		!atomic_dec_and_test(&qdisc->refcnt))
+	    !atomic_dec_and_test(&qdisc->refcnt))
 		return;
 
-	if (!list_empty(&qdisc->list)) {
-		if (qdisc->ops->cl_ops == NULL)
-			list_del(&qdisc->list);
-		else
-			list_move(&qdisc->list, &cql);
-	}
+	list_del(&qdisc->list);
+#ifdef CONFIG_NET_ESTIMATOR
+	gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
+#endif
+	if (ops->reset)
+		ops->reset(qdisc);
+	if (ops->destroy)
+		ops->destroy(qdisc);
 
-	/* unlink inner qdiscs from dev->qdisc_list immediately */
-	list_for_each_entry(cq, &cql, list)
-		list_for_each_entry_safe(q, n, &qdisc->dev->qdisc_list, list)
-			if (TC_H_MAJ(q->parent) == TC_H_MAJ(cq->handle)) {
-				if (q->ops->cl_ops == NULL)
-					list_del_init(&q->list);
-				else
-					list_move_tail(&q->list, &cql);
-			}
-	list_for_each_entry_safe(cq, n, &cql, list)
-		list_del_init(&cq->list);
-
+	module_put(ops->owner);
+	dev_put(qdisc->dev);
 	call_rcu(&qdisc->q_rcu, __qdisc_destroy);
 }
 
@@ -549,15 +525,15 @@
 				printk(KERN_INFO "%s: activation failed\n", dev->name);
 				return;
 			}
-			write_lock_bh(&qdisc_tree_lock);
+			write_lock(&qdisc_tree_lock);
 			list_add_tail(&qdisc->list, &dev->qdisc_list);
-			write_unlock_bh(&qdisc_tree_lock);
+			write_unlock(&qdisc_tree_lock);
 		} else {
 			qdisc =  &noqueue_qdisc;
 		}
-		write_lock_bh(&qdisc_tree_lock);
+		write_lock(&qdisc_tree_lock);
 		dev->qdisc_sleeping = qdisc;
-		write_unlock_bh(&qdisc_tree_lock);
+		write_unlock(&qdisc_tree_lock);
 	}
 
 	if (!netif_carrier_ok(dev))
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index bb3ddd4..6c058e3 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -391,7 +391,7 @@
 /* If this triggers, it is a bug in this code, but it need not be fatal */
 static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
 {
-	if (RB_EMPTY_NODE(rb)) {
+	if (!RB_EMPTY_NODE(rb)) {
 		WARN_ON(1);
 	} else {
 		rb_erase(rb, root);
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 55163af..993ff1a 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -331,8 +331,8 @@
 	task->tk_msg.rpc_cred = NULL;
 }
 
-u32 *
-rpcauth_marshcred(struct rpc_task *task, u32 *p)
+__be32 *
+rpcauth_marshcred(struct rpc_task *task, __be32 *p)
 {
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
@@ -342,8 +342,8 @@
 	return cred->cr_ops->crmarshal(task, p);
 }
 
-u32 *
-rpcauth_checkverf(struct rpc_task *task, u32 *p)
+__be32 *
+rpcauth_checkverf(struct rpc_task *task, __be32 *p)
 {
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
 
@@ -355,7 +355,7 @@
 
 int
 rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
-		u32 *data, void *obj)
+		__be32 *data, void *obj)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
@@ -369,7 +369,7 @@
 
 int
 rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
-		u32 *data, void *obj)
+		__be32 *data, void *obj)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 6eed3e1..a6ed2d2 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -826,14 +826,14 @@
 * Marshal credentials.
 * Maybe we should keep a cached credential for performance reasons.
 */
-static u32 *
-gss_marshal(struct rpc_task *task, u32 *p)
+static __be32 *
+gss_marshal(struct rpc_task *task, __be32 *p)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 	struct gss_cred	*gss_cred = container_of(cred, struct gss_cred,
 						 gc_base);
 	struct gss_cl_ctx	*ctx = gss_cred_get_ctx(cred);
-	u32		*cred_len;
+	__be32		*cred_len;
 	struct rpc_rqst *req = task->tk_rqstp;
 	u32             maj_stat = 0;
 	struct xdr_netobj mic;
@@ -894,12 +894,12 @@
 	return 0;
 }
 
-static u32 *
-gss_validate(struct rpc_task *task, u32 *p)
+static __be32 *
+gss_validate(struct rpc_task *task, __be32 *p)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-	u32		seq;
+	__be32		seq;
 	struct kvec	iov;
 	struct xdr_buf	verf_buf;
 	struct xdr_netobj mic;
@@ -940,13 +940,14 @@
 
 static inline int
 gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-		kxdrproc_t encode, struct rpc_rqst *rqstp, u32 *p, void *obj)
+		kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj)
 {
 	struct xdr_buf	*snd_buf = &rqstp->rq_snd_buf;
 	struct xdr_buf	integ_buf;
-	u32             *integ_len = NULL;
+	__be32          *integ_len = NULL;
 	struct xdr_netobj mic;
-	u32		offset, *q;
+	u32		offset;
+	__be32		*q;
 	struct kvec	*iov;
 	u32             maj_stat = 0;
 	int		status = -EIO;
@@ -1032,13 +1033,13 @@
 
 static inline int
 gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-		kxdrproc_t encode, struct rpc_rqst *rqstp, u32 *p, void *obj)
+		kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj)
 {
 	struct xdr_buf	*snd_buf = &rqstp->rq_snd_buf;
 	u32		offset;
 	u32             maj_stat;
 	int		status;
-	u32		*opaque_len;
+	__be32		*opaque_len;
 	struct page	**inpages;
 	int		first;
 	int		pad;
@@ -1095,7 +1096,7 @@
 
 static int
 gss_wrap_req(struct rpc_task *task,
-	     kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
+	     kxdrproc_t encode, void *rqstp, __be32 *p, void *obj)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 	struct gss_cred	*gss_cred = container_of(cred, struct gss_cred,
@@ -1132,7 +1133,7 @@
 
 static inline int
 gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-		struct rpc_rqst *rqstp, u32 **p)
+		struct rpc_rqst *rqstp, __be32 **p)
 {
 	struct xdr_buf	*rcv_buf = &rqstp->rq_rcv_buf;
 	struct xdr_buf integ_buf;
@@ -1169,7 +1170,7 @@
 
 static inline int
 gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-		struct rpc_rqst *rqstp, u32 **p)
+		struct rpc_rqst *rqstp, __be32 **p)
 {
 	struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
 	u32 offset;
@@ -1198,13 +1199,13 @@
 
 static int
 gss_unwrap_resp(struct rpc_task *task,
-		kxdrproc_t decode, void *rqstp, u32 *p, void *obj)
+		kxdrproc_t decode, void *rqstp, __be32 *p, void *obj)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
 			gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-	u32		*savedp = p;
+	__be32		*savedp = p;
 	struct kvec	*head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
 	int		savedlen = head->iov_len;
 	int             status = -EIO;
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 2f31216..08601ee 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -115,7 +115,7 @@
 	krb5_hdr = ptr - 2;
 	msg_start = krb5_hdr + 24;
 
-	*(u16 *)(krb5_hdr + 2) = htons(ctx->signalg);
+	*(__be16 *)(krb5_hdr + 2) = htons(ctx->signalg);
 	memset(krb5_hdr + 4, 0xff, 4);
 
 	if (make_checksum(checksum_type, krb5_hdr, 8, text, 0, &md5cksum))
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index f179415..cc45c16 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -177,9 +177,9 @@
 	msg_start = krb5_hdr + 24;
 	/* XXXJBF: */ BUG_ON(buf->head[0].iov_base + offset + headlen != msg_start + blocksize);
 
-	*(u16 *)(krb5_hdr + 2) = htons(kctx->signalg);
+	*(__be16 *)(krb5_hdr + 2) = htons(kctx->signalg);
 	memset(krb5_hdr + 4, 0xff, 4);
-	*(u16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
+	*(__be16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
 
 	make_confounder(msg_start, blocksize);
 
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 94217ec..638c0b5 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -607,7 +607,7 @@
 
 	if (argv->iov_len < 4)
 		return -1;
-	o->len = ntohl(svc_getu32(argv));
+	o->len = svc_getnl(argv);
 	l = round_up_to_quad(o->len);
 	if (argv->iov_len < l)
 		return -1;
@@ -620,17 +620,17 @@
 static inline int
 svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
 {
-	u32 *p;
+	u8 *p;
 
 	if (resv->iov_len + 4 > PAGE_SIZE)
 		return -1;
-	svc_putu32(resv, htonl(o->len));
+	svc_putnl(resv, o->len);
 	p = resv->iov_base + resv->iov_len;
 	resv->iov_len += round_up_to_quad(o->len);
 	if (resv->iov_len > PAGE_SIZE)
 		return -1;
 	memcpy(p, o->data, o->len);
-	memset((u8 *)p + o->len, 0, round_up_to_quad(o->len) - o->len);
+	memset(p + o->len, 0, round_up_to_quad(o->len) - o->len);
 	return 0;
 }
 
@@ -640,7 +640,7 @@
  */
 static int
 gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
-		  u32 *rpcstart, struct rpc_gss_wire_cred *gc, u32 *authp)
+		  __be32 *rpcstart, struct rpc_gss_wire_cred *gc, __be32 *authp)
 {
 	struct gss_ctx		*ctx_id = rsci->mechctx;
 	struct xdr_buf		rpchdr;
@@ -657,7 +657,7 @@
 	*authp = rpc_autherr_badverf;
 	if (argv->iov_len < 4)
 		return SVC_DENIED;
-	flavor = ntohl(svc_getu32(argv));
+	flavor = svc_getnl(argv);
 	if (flavor != RPC_AUTH_GSS)
 		return SVC_DENIED;
 	if (svc_safe_getnetobj(argv, &checksum))
@@ -687,9 +687,9 @@
 static int
 gss_write_null_verf(struct svc_rqst *rqstp)
 {
-	u32     *p;
+	__be32     *p;
 
-	svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_NULL));
+	svc_putnl(rqstp->rq_res.head, RPC_AUTH_NULL);
 	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
 	/* don't really need to check if head->iov_len > PAGE_SIZE ... */
 	*p++ = 0;
@@ -701,14 +701,14 @@
 static int
 gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
 {
-	u32			xdr_seq;
+	__be32			xdr_seq;
 	u32			maj_stat;
 	struct xdr_buf		verf_data;
 	struct xdr_netobj	mic;
-	u32			*p;
+	__be32			*p;
 	struct kvec		iov;
 
-	svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_GSS));
+	svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
 	xdr_seq = htonl(seq);
 
 	iov.iov_base = &xdr_seq;
@@ -782,7 +782,7 @@
 static inline int
 read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
 {
-	u32     raw;
+	__be32  raw;
 	int     status;
 
 	status = read_bytes_from_xdr_buf(buf, base, &raw, sizeof(*obj));
@@ -805,7 +805,7 @@
 	struct xdr_netobj mic;
 	struct xdr_buf integ_buf;
 
-	integ_len = ntohl(svc_getu32(&buf->head[0]));
+	integ_len = svc_getnl(&buf->head[0]);
 	if (integ_len & 3)
 		goto out;
 	if (integ_len > buf->len)
@@ -825,7 +825,7 @@
 	maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
 	if (maj_stat != GSS_S_COMPLETE)
 		goto out;
-	if (ntohl(svc_getu32(&buf->head[0])) != seq)
+	if (svc_getnl(&buf->head[0]) != seq)
 		goto out;
 	stat = 0;
 out:
@@ -857,7 +857,7 @@
 
 	rqstp->rq_sendfile_ok = 0;
 
-	priv_len = ntohl(svc_getu32(&buf->head[0]));
+	priv_len = svc_getnl(&buf->head[0]);
 	if (rqstp->rq_deferred) {
 		/* Already decrypted last time through! The sequence number
 		 * check at out_seq is unnecessary but harmless: */
@@ -895,7 +895,7 @@
 	if (maj_stat != GSS_S_COMPLETE)
 		return -EINVAL;
 out_seq:
-	if (ntohl(svc_getu32(&buf->head[0])) != seq)
+	if (svc_getnl(&buf->head[0]) != seq)
 		return -EINVAL;
 	return 0;
 }
@@ -905,7 +905,7 @@
 	struct rpc_gss_wire_cred	clcred;
 	/* pointer to the beginning of the procedure-specific results,
 	 * which may be encrypted/checksummed in svcauth_gss_release: */
-	u32				*body_start;
+	__be32				*body_start;
 	struct rsc			*rsci;
 };
 
@@ -946,7 +946,7 @@
  * response here and return SVC_COMPLETE.
  */
 static int
-svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
+svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
 	struct kvec	*argv = &rqstp->rq_arg.head[0];
 	struct kvec	*resv = &rqstp->rq_res.head[0];
@@ -956,8 +956,8 @@
 	struct rpc_gss_wire_cred *gc;
 	struct rsc	*rsci = NULL;
 	struct rsi	*rsip, rsikey;
-	u32		*rpcstart;
-	u32		*reject_stat = resv->iov_base + resv->iov_len;
+	__be32		*rpcstart;
+	__be32		*reject_stat = resv->iov_base + resv->iov_len;
 	int		ret;
 
 	dprintk("RPC:      svcauth_gss: argv->iov_len = %zd\n",argv->iov_len);
@@ -985,12 +985,12 @@
 
 	if (argv->iov_len < 5 * 4)
 		goto auth_err;
-	crlen = ntohl(svc_getu32(argv));
-	if (ntohl(svc_getu32(argv)) != RPC_GSS_VERSION)
+	crlen = svc_getnl(argv);
+	if (svc_getnl(argv) != RPC_GSS_VERSION)
 		goto auth_err;
-	gc->gc_proc = ntohl(svc_getu32(argv));
-	gc->gc_seq = ntohl(svc_getu32(argv));
-	gc->gc_svc = ntohl(svc_getu32(argv));
+	gc->gc_proc = svc_getnl(argv);
+	gc->gc_seq = svc_getnl(argv);
+	gc->gc_svc = svc_getnl(argv);
 	if (svc_safe_getnetobj(argv, &gc->gc_ctx))
 		goto auth_err;
 	if (crlen != round_up_to_quad(gc->gc_ctx.len) + 5 * 4)
@@ -1016,9 +1016,9 @@
 	case RPC_GSS_PROC_CONTINUE_INIT:
 		if (argv->iov_len < 2 * 4)
 			goto auth_err;
-		if (ntohl(svc_getu32(argv)) != RPC_AUTH_NULL)
+		if (svc_getnl(argv) != RPC_AUTH_NULL)
 			goto auth_err;
-		if (ntohl(svc_getu32(argv)) != 0)
+		if (svc_getnl(argv) != 0)
 			goto auth_err;
 		break;
 	case RPC_GSS_PROC_DATA:
@@ -1076,14 +1076,14 @@
 				goto drop;
 			if (resv->iov_len + 4 > PAGE_SIZE)
 				goto drop;
-			svc_putu32(resv, rpc_success);
+			svc_putnl(resv, RPC_SUCCESS);
 			if (svc_safe_putnetobj(resv, &rsip->out_handle))
 				goto drop;
 			if (resv->iov_len + 3 * 4 > PAGE_SIZE)
 				goto drop;
-			svc_putu32(resv, htonl(rsip->major_status));
-			svc_putu32(resv, htonl(rsip->minor_status));
-			svc_putu32(resv, htonl(GSS_SEQ_WIN));
+			svc_putnl(resv, rsip->major_status);
+			svc_putnl(resv, rsip->minor_status);
+			svc_putnl(resv, GSS_SEQ_WIN);
 			if (svc_safe_putnetobj(resv, &rsip->out_token))
 				goto drop;
 			rqstp->rq_client = NULL;
@@ -1093,7 +1093,7 @@
 		set_bit(CACHE_NEGATIVE, &rsci->h.flags);
 		if (resv->iov_len + 4 > PAGE_SIZE)
 			goto drop;
-		svc_putu32(resv, rpc_success);
+		svc_putnl(resv, RPC_SUCCESS);
 		goto complete;
 	case RPC_GSS_PROC_DATA:
 		*authp = rpcsec_gsserr_ctxproblem;
@@ -1111,8 +1111,8 @@
 				goto auth_err;
 			/* placeholders for length and seq. number: */
 			svcdata->body_start = resv->iov_base + resv->iov_len;
-			svc_putu32(resv, 0);
-			svc_putu32(resv, 0);
+			svc_putnl(resv, 0);
+			svc_putnl(resv, 0);
 			break;
 		case RPC_GSS_SVC_PRIVACY:
 			if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
@@ -1120,8 +1120,8 @@
 				goto auth_err;
 			/* placeholders for length and seq. number: */
 			svcdata->body_start = resv->iov_base + resv->iov_len;
-			svc_putu32(resv, 0);
-			svc_putu32(resv, 0);
+			svc_putnl(resv, 0);
+			svc_putnl(resv, 0);
 			break;
 		default:
 			goto auth_err;
@@ -1156,7 +1156,7 @@
 	struct xdr_buf integ_buf;
 	struct xdr_netobj mic;
 	struct kvec *resv;
-	u32 *p;
+	__be32 *p;
 	int integ_offset, integ_len;
 	int stat = -EINVAL;
 
@@ -1199,7 +1199,7 @@
 	mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
 	if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
 		goto out_err;
-	svc_putu32(resv, htonl(mic.len));
+	svc_putnl(resv, mic.len);
 	memset(mic.data + mic.len, 0,
 			round_up_to_quad(mic.len) - mic.len);
 	resv->iov_len += XDR_QUADLEN(mic.len) << 2;
@@ -1219,8 +1219,8 @@
 	struct rpc_gss_wire_cred *gc = &gsd->clcred;
 	struct xdr_buf *resbuf = &rqstp->rq_res;
 	struct page **inpages = NULL;
-	u32 *p;
-	int offset, *len;
+	__be32 *p, *len;
+	int offset;
 	int pad;
 
 	p = gsd->body_start;
@@ -1264,7 +1264,7 @@
 		return -ENOMEM;
 	*len = htonl(resbuf->len - offset);
 	pad = 3 - ((resbuf->len - offset - 1)&3);
-	p = (u32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
+	p = (__be32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
 	memset(p, 0, pad);
 	resbuf->tail[0].iov_len += pad;
 	resbuf->len += pad;
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 2eccffa..3be257d 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -60,8 +60,8 @@
 /*
  * Marshal credential.
  */
-static u32 *
-nul_marshal(struct rpc_task *task, u32 *p)
+static __be32 *
+nul_marshal(struct rpc_task *task, __be32 *p)
 {
 	*p++ = htonl(RPC_AUTH_NULL);
 	*p++ = 0;
@@ -81,8 +81,8 @@
 	return 0;
 }
 
-static u32 *
-nul_validate(struct rpc_task *task, u32 *p)
+static __be32 *
+nul_validate(struct rpc_task *task, __be32 *p)
 {
 	rpc_authflavor_t	flavor;
 	u32			size;
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 74c7406..f7f990c 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -137,12 +137,12 @@
  * Marshal credentials.
  * Maybe we should keep a cached credential for performance reasons.
  */
-static u32 *
-unx_marshal(struct rpc_task *task, u32 *p)
+static __be32 *
+unx_marshal(struct rpc_task *task, __be32 *p)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
 	struct unx_cred	*cred = (struct unx_cred *) task->tk_msg.rpc_cred;
-	u32		*base, *hold;
+	__be32		*base, *hold;
 	int		i;
 
 	*p++ = htonl(RPC_AUTH_UNIX);
@@ -178,8 +178,8 @@
 	return 0;
 }
 
-static u32 *
-unx_validate(struct rpc_task *task, u32 *p)
+static __be32 *
+unx_validate(struct rpc_task *task, __be32 *p)
 {
 	rpc_authflavor_t	flavor;
 	u32			size;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 084a0ad..124ff0c 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -60,8 +60,8 @@
 static void	call_timeout(struct rpc_task *task);
 static void	call_connect(struct rpc_task *task);
 static void	call_connect_status(struct rpc_task *task);
-static u32 *	call_header(struct rpc_task *task);
-static u32 *	call_verify(struct rpc_task *task);
+static __be32 *	call_header(struct rpc_task *task);
+static __be32 *	call_verify(struct rpc_task *task);
 
 
 static int
@@ -782,7 +782,7 @@
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	unsigned int	bufsiz;
 	kxdrproc_t	encode;
-	u32		*p;
+	__be32		*p;
 
 	dprintk("RPC: %4d call_encode (status %d)\n", 
 				task->tk_pid, task->tk_status);
@@ -1100,7 +1100,7 @@
 	struct rpc_clnt	*clnt = task->tk_client;
 	struct rpc_rqst	*req = task->tk_rqstp;
 	kxdrproc_t	decode = task->tk_msg.rpc_proc->p_decode;
-	u32		*p;
+	__be32		*p;
 
 	dprintk("RPC: %4d call_decode (status %d)\n", 
 				task->tk_pid, task->tk_status);
@@ -1197,12 +1197,12 @@
 /*
  * Call header serialization
  */
-static u32 *
+static __be32 *
 call_header(struct rpc_task *task)
 {
 	struct rpc_clnt *clnt = task->tk_client;
 	struct rpc_rqst	*req = task->tk_rqstp;
-	u32		*p = req->rq_svec[0].iov_base;
+	__be32		*p = req->rq_svec[0].iov_base;
 
 	/* FIXME: check buffer size? */
 
@@ -1221,12 +1221,13 @@
 /*
  * Reply header verification
  */
-static u32 *
+static __be32 *
 call_verify(struct rpc_task *task)
 {
 	struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
 	int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
-	u32	*p = iov->iov_base, n;
+	__be32	*p = iov->iov_base;
+	u32 n;
 	int error = -EACCES;
 
 	if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) {
@@ -1303,7 +1304,7 @@
 		printk(KERN_WARNING "call_verify: auth check failed\n");
 		goto out_garbage;		/* bad verifier, retry */
 	}
-	len = p - (u32 *)iov->iov_base - 1;
+	len = p - (__be32 *)iov->iov_base - 1;
 	if (len < 0)
 		goto out_overflow;
 	switch ((n = ntohl(*p++))) {
@@ -1358,12 +1359,12 @@
 	goto out_garbage;
 }
 
-static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj)
+static int rpcproc_encode_null(void *rqstp, __be32 *data, void *obj)
 {
 	return 0;
 }
 
-static int rpcproc_decode_null(void *rqstp, u32 *data, void *obj)
+static int rpcproc_decode_null(void *rqstp, __be32 *data, void *obj)
 {
 	return 0;
 }
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index c04609d..919d5ba 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -300,7 +300,7 @@
 /*
  * XDR encode/decode functions for PMAP
  */
-static int xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct portmap_args *map)
+static int xdr_encode_mapping(struct rpc_rqst *req, __be32 *p, struct portmap_args *map)
 {
 	dprintk("RPC: xdr_encode_mapping(%u, %u, %u, %u)\n",
 		map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
@@ -313,13 +313,13 @@
 	return 0;
 }
 
-static int xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp)
+static int xdr_decode_port(struct rpc_rqst *req, __be32 *p, unsigned short *portp)
 {
 	*portp = (unsigned short) ntohl(*p++);
 	return 0;
 }
 
-static int xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp)
+static int xdr_decode_bool(struct rpc_rqst *req, __be32 *p, unsigned int *boolp)
 {
 	*boolp = (unsigned int) ntohl(*p++);
 	return 0;
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index b76a227..44b8d9d 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -256,11 +256,11 @@
 	struct kvec *		argv = &rqstp->rq_arg.head[0];
 	struct kvec *		resv = &rqstp->rq_res.head[0];
 	kxdrproc_t		xdr;
-	u32			*statp;
-	u32			dir, prog, vers, proc,
-				auth_stat, rpc_stat;
+	__be32			*statp;
+	u32			dir, prog, vers, proc;
+	__be32			auth_stat, rpc_stat;
 	int			auth_res;
-	u32			*accept_statp;
+	__be32			*accept_statp;
 
 	rpc_stat = rpc_success;
 
@@ -284,16 +284,16 @@
 	rqstp->rq_sendfile_ok = 1;
 	/* tcp needs a space for the record length... */
 	if (rqstp->rq_prot == IPPROTO_TCP)
-		svc_putu32(resv, 0);
+		svc_putnl(resv, 0);
 
 	rqstp->rq_xid = svc_getu32(argv);
 	svc_putu32(resv, rqstp->rq_xid);
 
-	dir  = ntohl(svc_getu32(argv));
-	vers = ntohl(svc_getu32(argv));
+	dir  = svc_getnl(argv);
+	vers = svc_getnl(argv);
 
 	/* First words of reply: */
-	svc_putu32(resv, xdr_one);		/* REPLY */
+	svc_putnl(resv, 1);		/* REPLY */
 
 	if (dir != 0)		/* direction != CALL */
 		goto err_bad_dir;
@@ -303,11 +303,11 @@
 	/* Save position in case we later decide to reject: */
 	accept_statp = resv->iov_base + resv->iov_len;
 
-	svc_putu32(resv, xdr_zero);		/* ACCEPT */
+	svc_putnl(resv, 0);		/* ACCEPT */
 
-	rqstp->rq_prog = prog = ntohl(svc_getu32(argv));	/* program number */
-	rqstp->rq_vers = vers = ntohl(svc_getu32(argv));	/* version number */
-	rqstp->rq_proc = proc = ntohl(svc_getu32(argv));	/* procedure number */
+	rqstp->rq_prog = prog = svc_getnl(argv);	/* program number */
+	rqstp->rq_vers = vers = svc_getnl(argv);	/* version number */
+	rqstp->rq_proc = proc = svc_getnl(argv);	/* procedure number */
 
 	progp = serv->sv_program;
 
@@ -361,7 +361,7 @@
 
 	/* Build the reply header. */
 	statp = resv->iov_base +resv->iov_len;
-	svc_putu32(resv, rpc_success);		/* RPC_SUCCESS */
+	svc_putnl(resv, RPC_SUCCESS);
 
 	/* Bump per-procedure stats counter */
 	procp->pc_count++;
@@ -439,10 +439,10 @@
 
 err_bad_rpc:
 	serv->sv_stats->rpcbadfmt++;
-	svc_putu32(resv, xdr_one);	/* REJECT */
-	svc_putu32(resv, xdr_zero);	/* RPC_MISMATCH */
-	svc_putu32(resv, xdr_two);	/* Only RPCv2 supported */
-	svc_putu32(resv, xdr_two);
+	svc_putnl(resv, 1);	/* REJECT */
+	svc_putnl(resv, 0);	/* RPC_MISMATCH */
+	svc_putnl(resv, 2);	/* Only RPCv2 supported */
+	svc_putnl(resv, 2);
 	goto sendit;
 
 err_bad_auth:
@@ -450,15 +450,15 @@
 	serv->sv_stats->rpcbadauth++;
 	/* Restore write pointer to location of accept status: */
 	xdr_ressize_check(rqstp, accept_statp);
-	svc_putu32(resv, xdr_one);	/* REJECT */
-	svc_putu32(resv, xdr_one);	/* AUTH_ERROR */
-	svc_putu32(resv, auth_stat);	/* status */
+	svc_putnl(resv, 1);	/* REJECT */
+	svc_putnl(resv, 1);	/* AUTH_ERROR */
+	svc_putnl(resv, ntohl(auth_stat));	/* status */
 	goto sendit;
 
 err_bad_prog:
 	dprintk("svc: unknown program %d\n", prog);
 	serv->sv_stats->rpcbadfmt++;
-	svc_putu32(resv, rpc_prog_unavail);
+	svc_putnl(resv, RPC_PROG_UNAVAIL);
 	goto sendit;
 
 err_bad_vers:
@@ -466,9 +466,9 @@
 	printk("svc: unknown version (%d)\n", vers);
 #endif
 	serv->sv_stats->rpcbadfmt++;
-	svc_putu32(resv, rpc_prog_mismatch);
-	svc_putu32(resv, htonl(progp->pg_lovers));
-	svc_putu32(resv, htonl(progp->pg_hivers));
+	svc_putnl(resv, RPC_PROG_MISMATCH);
+	svc_putnl(resv, progp->pg_lovers);
+	svc_putnl(resv, progp->pg_hivers);
 	goto sendit;
 
 err_bad_proc:
@@ -476,7 +476,7 @@
 	printk("svc: unknown procedure (%d)\n", proc);
 #endif
 	serv->sv_stats->rpcbadfmt++;
-	svc_putu32(resv, rpc_proc_unavail);
+	svc_putnl(resv, RPC_PROC_UNAVAIL);
 	goto sendit;
 
 err_garbage:
@@ -486,6 +486,6 @@
 	rpc_stat = rpc_garbage_args;
 err_bad:
 	serv->sv_stats->rpcbadfmt++;
-	svc_putu32(resv, rpc_stat);
+	svc_putnl(resv, ntohl(rpc_stat));
 	goto sendit;
 }
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 5b28c61..8f2320a 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -35,14 +35,14 @@
 };
 
 int
-svc_authenticate(struct svc_rqst *rqstp, u32 *authp)
+svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
 {
 	rpc_authflavor_t	flavor;
 	struct auth_ops		*aops;
 
 	*authp = rpc_auth_ok;
 
-	flavor = ntohl(svc_getu32(&rqstp->rq_arg.head[0]));
+	flavor = svc_getnl(&rqstp->rq_arg.head[0]);
 
 	dprintk("svc: svc_authenticate (%d)\n", flavor);
 
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 7e5707e..1020d54 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -145,7 +145,7 @@
 {
 	char text_addr[20];
 	struct ip_map *im = container_of(h, struct ip_map, h);
-	__u32 addr = im->m_addr.s_addr;
+	__be32 addr = im->m_addr.s_addr;
 	
 	snprintf(text_addr, 20, "%u.%u.%u.%u",
 		 ntohl(addr) >> 24 & 0xff,
@@ -249,10 +249,10 @@
 
 	seq_printf(m, "%s %d.%d.%d.%d %s\n",
 		   im->m_class,
-		   htonl(addr.s_addr) >> 24 & 0xff,
-		   htonl(addr.s_addr) >> 16 & 0xff,
-		   htonl(addr.s_addr) >>  8 & 0xff,
-		   htonl(addr.s_addr) >>  0 & 0xff,
+		   ntohl(addr.s_addr) >> 24 & 0xff,
+		   ntohl(addr.s_addr) >> 16 & 0xff,
+		   ntohl(addr.s_addr) >>  8 & 0xff,
+		   ntohl(addr.s_addr) >>  0 & 0xff,
 		   dom
 		   );
 	return 0;
@@ -410,7 +410,7 @@
 }
 
 static int
-svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
+svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
 	struct kvec	*argv = &rqstp->rq_arg.head[0];
 	struct kvec	*resv = &rqstp->rq_res.head[0];
@@ -427,7 +427,7 @@
 		*authp = rpc_autherr_badcred;
 		return SVC_DENIED;
 	}
-	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 		dprintk("svc: bad null verf\n");
 		*authp = rpc_autherr_badverf;
 		return SVC_DENIED;
@@ -441,8 +441,8 @@
 		return SVC_DROP; /* kmalloc failure - client must retry */
 
 	/* Put NULL verifier */
-	svc_putu32(resv, RPC_AUTH_NULL);
-	svc_putu32(resv, 0);
+	svc_putnl(resv, RPC_AUTH_NULL);
+	svc_putnl(resv, 0);
 
 	return SVC_OK;
 }
@@ -472,7 +472,7 @@
 
 
 static int
-svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
+svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
 	struct kvec	*argv = &rqstp->rq_arg.head[0];
 	struct kvec	*resv = &rqstp->rq_res.head[0];
@@ -488,31 +488,31 @@
 
 	svc_getu32(argv);			/* length */
 	svc_getu32(argv);			/* time stamp */
-	slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));	/* machname length */
+	slen = XDR_QUADLEN(svc_getnl(argv));	/* machname length */
 	if (slen > 64 || (len -= (slen + 3)*4) < 0)
 		goto badcred;
-	argv->iov_base = (void*)((u32*)argv->iov_base + slen);	/* skip machname */
+	argv->iov_base = (void*)((__be32*)argv->iov_base + slen);	/* skip machname */
 	argv->iov_len -= slen*4;
 
-	cred->cr_uid = ntohl(svc_getu32(argv));		/* uid */
-	cred->cr_gid = ntohl(svc_getu32(argv));		/* gid */
-	slen = ntohl(svc_getu32(argv));			/* gids length */
+	cred->cr_uid = svc_getnl(argv);		/* uid */
+	cred->cr_gid = svc_getnl(argv);		/* gid */
+	slen = svc_getnl(argv);			/* gids length */
 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
 		goto badcred;
 	cred->cr_group_info = groups_alloc(slen);
 	if (cred->cr_group_info == NULL)
 		return SVC_DROP;
 	for (i = 0; i < slen; i++)
-		GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv));
+		GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
 
-	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 		*authp = rpc_autherr_badverf;
 		return SVC_DENIED;
 	}
 
 	/* Put NULL verifier */
-	svc_putu32(resv, RPC_AUTH_NULL);
-	svc_putu32(resv, 0);
+	svc_putnl(resv, RPC_AUTH_NULL);
+	svc_putnl(resv, 0);
 
 	return SVC_OK;
 
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 953aff8..5b0fe1b 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1030,7 +1030,7 @@
 {
 	struct xdr_buf	*xbufp = &rqstp->rq_res;
 	int sent;
-	u32 reclen;
+	__be32 reclen;
 
 	/* Set up the first element of the reply kvec.
 	 * Any other kvecs that may be in use have been taken
@@ -1393,14 +1393,12 @@
 	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
 		return error;
 
-	if (sin != NULL) {
-		if (type == SOCK_STREAM)
-			sock->sk->sk_reuse = 1; /* allow address reuse */
-		error = kernel_bind(sock, (struct sockaddr *) sin,
-						sizeof(*sin));
-		if (error < 0)
-			goto bummer;
-	}
+	if (type == SOCK_STREAM)
+		sock->sk->sk_reuse = 1; /* allow address reuse */
+	error = kernel_bind(sock, (struct sockaddr *) sin,
+					sizeof(*sin));
+	if (error < 0)
+		goto bummer;
 
 	if (protocol == IPPROTO_TCP) {
 		if ((error = kernel_listen(sock, 64)) < 0)
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 6ac4510..9022eb8 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -18,8 +18,8 @@
 /*
  * XDR functions for basic NFS types
  */
-u32 *
-xdr_encode_netobj(u32 *p, const struct xdr_netobj *obj)
+__be32 *
+xdr_encode_netobj(__be32 *p, const struct xdr_netobj *obj)
 {
 	unsigned int	quadlen = XDR_QUADLEN(obj->len);
 
@@ -29,8 +29,8 @@
 	return p + XDR_QUADLEN(obj->len);
 }
 
-u32 *
-xdr_decode_netobj(u32 *p, struct xdr_netobj *obj)
+__be32 *
+xdr_decode_netobj(__be32 *p, struct xdr_netobj *obj)
 {
 	unsigned int	len;
 
@@ -55,7 +55,7 @@
  * Returns the updated current XDR buffer position
  *
  */
-u32 *xdr_encode_opaque_fixed(u32 *p, const void *ptr, unsigned int nbytes)
+__be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int nbytes)
 {
 	if (likely(nbytes != 0)) {
 		unsigned int quadlen = XDR_QUADLEN(nbytes);
@@ -79,21 +79,21 @@
  *
  * Returns the updated current XDR buffer position
  */
-u32 *xdr_encode_opaque(u32 *p, const void *ptr, unsigned int nbytes)
+__be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int nbytes)
 {
 	*p++ = htonl(nbytes);
 	return xdr_encode_opaque_fixed(p, ptr, nbytes);
 }
 EXPORT_SYMBOL(xdr_encode_opaque);
 
-u32 *
-xdr_encode_string(u32 *p, const char *string)
+__be32 *
+xdr_encode_string(__be32 *p, const char *string)
 {
 	return xdr_encode_array(p, string, strlen(string));
 }
 
-u32 *
-xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen)
+__be32 *
+xdr_decode_string_inplace(__be32 *p, char **sp, int *lenp, int maxlen)
 {
 	unsigned int	len;
 
@@ -432,7 +432,7 @@
  *	 of the buffer length, and takes care of adjusting the kvec
  *	 length for us.
  */
-void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
+void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
 {
 	struct kvec *iov = buf->head;
 	int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len;
@@ -440,8 +440,8 @@
 	BUG_ON(scratch_len < 0);
 	xdr->buf = buf;
 	xdr->iov = iov;
-	xdr->p = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
-	xdr->end = (uint32_t *)((char *)iov->iov_base + scratch_len);
+	xdr->p = (__be32 *)((char *)iov->iov_base + iov->iov_len);
+	xdr->end = (__be32 *)((char *)iov->iov_base + scratch_len);
 	BUG_ON(iov->iov_len > scratch_len);
 
 	if (p != xdr->p && p != NULL) {
@@ -465,10 +465,10 @@
  * bytes of data. If so, update the total xdr_buf length, and
  * adjust the length of the current kvec.
  */
-uint32_t * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)
+__be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)
 {
-	uint32_t *p = xdr->p;
-	uint32_t *q;
+	__be32 *p = xdr->p;
+	__be32 *q;
 
 	/* align nbytes on the next 32-bit boundary */
 	nbytes += 3;
@@ -524,7 +524,7 @@
  * @buf: pointer to XDR buffer from which to decode data
  * @p: current pointer inside XDR buffer
  */
-void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
+void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
 {
 	struct kvec *iov = buf->head;
 	unsigned int len = iov->iov_len;
@@ -534,7 +534,7 @@
 	xdr->buf = buf;
 	xdr->iov = iov;
 	xdr->p = p;
-	xdr->end = (uint32_t *)((char *)iov->iov_base + len);
+	xdr->end = (__be32 *)((char *)iov->iov_base + len);
 }
 EXPORT_SYMBOL(xdr_init_decode);
 
@@ -548,10 +548,10 @@
  * If so return the current pointer, then update the current
  * pointer position.
  */
-uint32_t * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
+__be32 * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
 {
-	uint32_t *p = xdr->p;
-	uint32_t *q = p + XDR_QUADLEN(nbytes);
+	__be32 *p = xdr->p;
+	__be32 *q = p + XDR_QUADLEN(nbytes);
 
 	if (unlikely(q > xdr->end || q < p))
 		return NULL;
@@ -599,8 +599,8 @@
 	 * Position current pointer at beginning of tail, and
 	 * set remaining message length.
 	 */
-	xdr->p = (uint32_t *)((char *)iov->iov_base + padding);
-	xdr->end = (uint32_t *)((char *)iov->iov_base + end);
+	xdr->p = (__be32 *)((char *)iov->iov_base + padding);
+	xdr->end = (__be32 *)((char *)iov->iov_base + end);
 }
 EXPORT_SYMBOL(xdr_read_pages);
 
@@ -624,8 +624,8 @@
 	 */
 	if (len > PAGE_CACHE_SIZE - xdr->buf->page_base)
 		len = PAGE_CACHE_SIZE - xdr->buf->page_base;
-	xdr->p = (uint32_t *)(kaddr + xdr->buf->page_base);
-	xdr->end = (uint32_t *)((char *)xdr->p + len);
+	xdr->p = (__be32 *)(kaddr + xdr->buf->page_base);
+	xdr->end = (__be32 *)((char *)xdr->p + len);
 }
 EXPORT_SYMBOL(xdr_enter_page);
 
@@ -743,7 +743,7 @@
 int
 xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj)
 {
-	u32	raw;
+	__be32	raw;
 	int	status;
 
 	status = read_bytes_from_xdr_buf(buf, base, &raw, sizeof(*obj));
@@ -756,7 +756,7 @@
 int
 xdr_encode_word(struct xdr_buf *buf, int base, u32 obj)
 {
-	u32	raw = htonl(obj);
+	__be32	raw = htonl(obj);
 
 	return write_bytes_to_xdr_buf(buf, base, &raw, sizeof(obj));
 }
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1f786f6..8085747 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -594,7 +594,7 @@
  * @xid: RPC XID of incoming reply
  *
  */
-struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
 {
 	struct list_head *pos;
 
@@ -801,7 +801,7 @@
 	spin_unlock(&xprt->reserve_lock);
 }
 
-static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
+static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
 	return xprt->xid++;
 }
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 9b62923..28100e0 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -548,7 +548,8 @@
 	struct rpc_rqst *rovr;
 	struct sk_buff *skb;
 	int err, repsize, copied;
-	u32 _xid, *xp;
+	u32 _xid;
+	__be32 *xp;
 
 	read_lock(&sk->sk_callback_lock);
 	dprintk("RPC:      xs_udp_data_ready...\n");
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h
index d3abb0b..6ac4e4f 100644
--- a/net/xfrm/xfrm_hash.h
+++ b/net/xfrm/xfrm_hash.h
@@ -58,10 +58,10 @@
 }
 
 static inline unsigned int
-__xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family,
+__xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family,
 		unsigned int hmask)
 {
-	unsigned int h = spi ^ proto;
+	unsigned int h = (__force u32)spi ^ proto;
 	switch (family) {
 	case AF_INET:
 		h ^= __xfrm4_addr_hash(daddr);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index dfc90bb..e8198a2 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -46,7 +46,7 @@
 
 /* Fetch spi and seq from ipsec header */
 
-int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 {
 	int offset, offset_seq;
 
@@ -62,7 +62,7 @@
 	case IPPROTO_COMP:
 		if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr)))
 			return -EINVAL;
-		*spi = htonl(ntohs(*(u16*)(skb->h.raw + 2)));
+		*spi = htonl(ntohs(*(__be16*)(skb->h.raw + 2)));
 		*seq = 0;
 		return 0;
 	default:
@@ -72,8 +72,8 @@
 	if (!pskb_may_pull(skb, 16))
 		return -EINVAL;
 
-	*spi = *(u32*)(skb->h.raw + offset);
-	*seq = *(u32*)(skb->h.raw + offset_seq);
+	*spi = *(__be32*)(skb->h.raw + offset);
+	*seq = *(__be32*)(skb->h.raw + offset_seq);
 	return 0;
 }
 EXPORT_SYMBOL(xfrm_parse_spi);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9f63edd..f927b73 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -70,7 +70,7 @@
 }
 
 static inline unsigned int
-xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
+xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
 {
 	return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
 }
@@ -96,9 +96,12 @@
 				    nhashmask);
 		hlist_add_head(&x->bysrc, nsrctable+h);
 
-		h = __xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
-				    x->props.family, nhashmask);
-		hlist_add_head(&x->byspi, nspitable+h);
+		if (x->id.spi) {
+			h = __xfrm_spi_hash(&x->id.daddr, x->id.spi,
+					    x->id.proto, x->props.family,
+					    nhashmask);
+			hlist_add_head(&x->byspi, nspitable+h);
+		}
 	}
 }
 
@@ -421,7 +424,7 @@
 	return 0;
 }
 
-static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
+static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
 {
 	unsigned int h = xfrm_spi_hash(daddr, spi, proto, family);
 	struct xfrm_state *x;
@@ -622,7 +625,7 @@
 	h = xfrm_src_hash(&x->props.saddr, x->props.family);
 	hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
 
-	if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) {
+	if (x->id.spi) {
 		h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
 				  x->props.family);
 
@@ -916,7 +919,7 @@
 EXPORT_SYMBOL(xfrm_state_check);
 
 struct xfrm_state *
-xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
+xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto,
 		  unsigned short family)
 {
 	struct xfrm_state *x;
@@ -1040,7 +1043,7 @@
 EXPORT_SYMBOL(xfrm_get_acqseq);
 
 void
-xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
+xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi)
 {
 	unsigned int h;
 	struct xfrm_state *x0;
@@ -1057,10 +1060,10 @@
 		x->id.spi = minspi;
 	} else {
 		u32 spi = 0;
-		minspi = ntohl(minspi);
-		maxspi = ntohl(maxspi);
-		for (h=0; h<maxspi-minspi+1; h++) {
-			spi = minspi + net_random()%(maxspi-minspi+1);
+		u32 low = ntohl(minspi);
+		u32 high = ntohl(maxspi);
+		for (h=0; h<high-low+1; h++) {
+			spi = low + net_random()%(high-low+1);
 			x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);
 			if (x0 == NULL) {
 				x->id.spi = htonl(spi);
@@ -1180,11 +1183,10 @@
 	spin_unlock(&x->lock);
 }
 
-int xfrm_replay_check(struct xfrm_state *x, u32 seq)
+int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq)
 {
 	u32 diff;
-
-	seq = ntohl(seq);
+	u32 seq = ntohl(net_seq);
 
 	if (unlikely(seq == 0))
 		return -EINVAL;
@@ -1206,11 +1208,10 @@
 }
 EXPORT_SYMBOL(xfrm_replay_check);
 
-void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
+void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
 {
 	u32 diff;
-
-	seq = ntohl(seq);
+	u32 seq = ntohl(net_seq);
 
 	if (seq > x->replay.seq) {
 		diff = seq - x->replay.seq;
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
index cb02baa..4ab6cbf 100644
--- a/scripts/basic/docproc.c
+++ b/scripts/basic/docproc.c
@@ -177,6 +177,7 @@
 		{
 			fprintf(stderr, "docproc: ");
 			perror(real_filename);
+			exit(1);
 		}
 		while(fgets(line, MAXLINESZ, fp)) {
 			char *p;
diff --git a/security/Kconfig b/security/Kconfig
index 67785df..460e5c9 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -93,18 +93,6 @@
 	  
 	  If you are unsure how to answer this question, answer N.
 
-config SECURITY_SECLVL
-	tristate "BSD Secure Levels"
-	depends on SECURITY
-	select CRYPTO
-	select CRYPTO_SHA1
-	help
-	  Implements BSD Secure Levels as an LSM.  See
-	  <file:Documentation/seclvl.txt> for instructions on how to use this
-	  module.
-
-	  If you are unsure how to answer this question, answer N.
-
 source security/selinux/Kconfig
 
 endmenu
diff --git a/security/Makefile b/security/Makefile
index 8cbbf2f..ef87df2 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,4 +16,3 @@
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
-obj-$(CONFIG_SECURITY_SECLVL)		+= seclvl.o
diff --git a/security/commoncap.c b/security/commoncap.c
index f50fc29..5a5ef5c 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -169,7 +169,7 @@
 	/* For init, we want to retain the capabilities set
 	 * in the init_task struct. Thus we skip the usual
 	 * capability rules */
-	if (current->pid != 1) {
+	if (!is_init(current)) {
 		current->cap_permitted = new_permitted;
 		current->cap_effective =
 		    cap_intersect (new_permitted, bprm->cap_effective);
diff --git a/security/seclvl.c b/security/seclvl.c
deleted file mode 100644
index 8f62919..0000000
--- a/security/seclvl.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/**
- * BSD Secure Levels LSM
- *
- * Maintainers:
- *	Michael A. Halcrow <mike@halcrow.us>
- *	Serge Hallyn <hallyn@cs.wm.edu>
- *
- * Copyright (c) 2001 WireX Communications, Inc <chris@wirex.com>
- * Copyright (c) 2001 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2002 International Business Machines <robb@austin.ibm.com>
- * Copyright (c) 2006 Davi E. M. Arnaut <davi.arnaut@gmail.com>
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/security.h>
-#include <linux/netlink.h>
-#include <linux/fs.h>
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include <linux/capability.h>
-#include <linux/time.h>
-#include <linux/proc_fs.h>
-#include <linux/kobject.h>
-#include <linux/crypto.h>
-#include <asm/scatterlist.h>
-#include <linux/scatterlist.h>
-#include <linux/gfp.h>
-#include <linux/sysfs.h>
-
-#define SHA1_DIGEST_SIZE 20
-
-/**
- * Module parameter that defines the initial secure level.
- *
- * When built as a module, it defaults to seclvl 1, which is the
- * behavior of BSD secure levels.  Note that this default behavior
- * wrecks havoc on a machine when the seclvl module is compiled into
- * the kernel.	In that case, we default to seclvl 0.
- */
-#ifdef CONFIG_SECURITY_SECLVL_MODULE
-static int initlvl = 1;
-#else
-static int initlvl;
-#endif
-module_param(initlvl, int, 0);
-MODULE_PARM_DESC(initlvl, "Initial secure level (defaults to 1)");
-
-/* Module parameter that defines the verbosity level */
-static int verbosity;
-module_param(verbosity, int, 0);
-MODULE_PARM_DESC(verbosity, "Initial verbosity level (0 or 1; defaults to "
-		 "0, which is Quiet)");
-
-/**
- * Optional password which can be passed in to bring seclvl to 0
- * (i.e., for halt/reboot).  Defaults to NULL (the passwd attribute
- * file will not be registered in sysfs).
- *
- * This gets converted to its SHA1 hash when stored.  It's probably
- * not a good idea to use this parameter when loading seclvl from a
- * script; use sha1_passwd instead.
- */
-
-#define MAX_PASSWD_SIZE	32
-static char passwd[MAX_PASSWD_SIZE];
-module_param_string(passwd, passwd, sizeof(passwd), 0);
-MODULE_PARM_DESC(passwd,
-		 "Plaintext of password that sets seclvl=0 when written to "
-		 "(sysfs mount point)/seclvl/passwd\n");
-
-/**
- * SHA1 hashed version of the optional password which can be passed in
- * to bring seclvl to 0 (i.e., for halt/reboot).  Must be in
- * hexadecimal format (40 characters).	Defaults to NULL (the passwd
- * attribute file will not be registered in sysfs).
- *
- * Use the sha1sum utility to generate the SHA1 hash of a password:
- *
- * echo -n "secret" | sha1sum
- */
-#define MAX_SHA1_PASSWD	41
-static char sha1_passwd[MAX_SHA1_PASSWD];
-module_param_string(sha1_passwd, sha1_passwd, sizeof(sha1_passwd), 0);
-MODULE_PARM_DESC(sha1_passwd,
-		 "SHA1 hash (40 hexadecimal characters) of password that "
-		 "sets seclvl=0 when plaintext password is written to "
-		 "(sysfs mount point)/seclvl/passwd\n");
-
-static int hideHash = 1;
-module_param(hideHash, int, 0);
-MODULE_PARM_DESC(hideHash, "When set to 0, reading seclvl/passwd from sysfs "
-		 "will return the SHA1-hashed value of the password that "
-		 "lowers the secure level to 0.\n");
-
-#define MY_NAME "seclvl"
-
-/**
- * This time-limits log writes to one per second.
- */
-#define seclvl_printk(verb, type, fmt, arg...)			\
-	do {							\
-		if (verbosity >= verb) {			\
-			static unsigned long _prior;		\
-			unsigned long _now = jiffies;		\
-			if ((_now - _prior) > HZ) {		\
-				printk(type "%s: %s: " fmt,	\
-					MY_NAME, __FUNCTION__ ,	\
-					## arg);		\
-				_prior = _now;			\
-			}					\
-		}						\
-	} while (0)
-
-/**
- * The actual security level.  Ranges between -1 and 2 inclusive.
- */
-static int seclvl;
-
-/**
- * flag to keep track of how we were registered
- */
-static int secondary;
-
-/**
- * Verifies that the requested secure level is valid, given the current
- * secure level.
- */
-static int seclvl_sanity(int reqlvl)
-{
-	if ((reqlvl < -1) || (reqlvl > 2)) {
-		seclvl_printk(1, KERN_WARNING, "Attempt to set seclvl out of "
-			      "range: [%d]\n", reqlvl);
-		return -EINVAL;
-	}
-	if ((seclvl == 0) && (reqlvl == -1))
-		return 0;
-	if (reqlvl < seclvl) {
-		seclvl_printk(1, KERN_WARNING, "Attempt to lower seclvl to "
-			      "[%d]\n", reqlvl);
-		return -EPERM;
-	}
-	return 0;
-}
-
-/**
- * security level advancement rules:
- *   Valid levels are -1 through 2, inclusive.
- *   From -1, stuck.  [ in case compiled into kernel ]
- *   From 0 or above, can only increment.
- */
-static void do_seclvl_advance(void *data, u64 val)
-{
-	int ret;
-	int newlvl = (int)val;
-
-	ret = seclvl_sanity(newlvl);
-	if (ret)
-		return;
-
-	if (newlvl > 2) {
-		seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
-			      "[%d]\n", newlvl);
-		return;
-	}
-	if (seclvl == -1) {
-		seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "
-			      "seclvl [%d]\n", seclvl);
-		return;
-	}
-	seclvl = newlvl;  /* would it be more "correct" to set *data? */
-	return;
-}
-
-static u64 seclvl_int_get(void *data)
-{
-	return *(int *)data;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(seclvl_file_ops, seclvl_int_get, do_seclvl_advance, "%lld\n");
-
-static unsigned char hashedPassword[SHA1_DIGEST_SIZE];
-
-/**
- * Converts a block of plaintext of into its SHA1 hashed value.
- *
- * It would be nice if crypto had a wrapper to do this for us linear
- * people...
- */
-static int
-plaintext_to_sha1(unsigned char *hash, const char *plaintext, unsigned int len)
-{
-	struct hash_desc desc;
-	struct scatterlist sg;
-	int err;
-
-	if (len > PAGE_SIZE) {
-		seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d "
-			      "characters).  Largest possible is %lu "
-			      "bytes.\n", len, PAGE_SIZE);
-		return -EINVAL;
-	}
-	desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(desc.tfm)) {
-		seclvl_printk(0, KERN_ERR,
-			      "Failed to load transform for SHA1\n");
-		return -EINVAL;
-	}
-	sg_init_one(&sg, (u8 *)plaintext, len);
-	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-	err = crypto_hash_digest(&desc, &sg, len, hash);
-	crypto_free_hash(desc.tfm);
-	return err;
-}
-
-/**
- * Called whenever the user writes to the sysfs passwd handle to this kernel
- * object.  It hashes the password and compares the hashed results.
- */
-static ssize_t
-passwd_write_file(struct file * file, const char __user * buf,
-				size_t count, loff_t *ppos)
-{
-	char *p;
-	int len;
-	unsigned char tmp[SHA1_DIGEST_SIZE];
-
-	if (!*passwd && !*sha1_passwd) {
-		seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "
-			      "seclvl module, but neither a plain text "
-			      "password nor a SHA1 hashed password was "
-			      "passed in as a module parameter!  This is a "
-			      "bug, since it should not be possible to be in "
-			      "this part of the module; please tell a "
-			      "maintainer about this event.\n");
-		return -EINVAL;
-	}
-
-	if (count >= PAGE_SIZE)
-		return -EINVAL;
-	if (*ppos != 0)
-		return -EINVAL;
-	p = kmalloc(count, GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-	len = -EFAULT;
-	if (copy_from_user(p, buf, count))
-		goto out;
-	
-	len = count;
-	/* ``echo "secret" > seclvl/passwd'' includes a newline */
-	if (p[len - 1] == '\n')
-		len--;
-	/* Hash the password, then compare the hashed values */
-	if ((len = plaintext_to_sha1(tmp, p, len))) {
-		seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
-			      "[%d]\n", len);
-		goto out;
-	}
-
-	len = -EPERM;
-	if (memcmp(hashedPassword, tmp, SHA1_DIGEST_SIZE))
-		goto out;
-
-	seclvl_printk(0, KERN_INFO,
-		      "Password accepted; seclvl reduced to 0.\n");
-	seclvl = 0;
-	len = count;
-
-out:
-	kfree (p);
-	return len;
-}
-
-static struct file_operations passwd_file_ops = {
-	.write = passwd_write_file,
-};
-
-/**
- * Explicitely disallow ptrace'ing the init process.
- */
-static int seclvl_ptrace(struct task_struct *parent, struct task_struct *child)
-{
-	if (seclvl >= 0 && child->pid == 1) {
-		seclvl_printk(1, KERN_WARNING, "Attempt to ptrace "
-			      "the init process dissallowed in "
-			      "secure level %d\n", seclvl);
-		return -EPERM;
-	}
-	return 0;
-}
-
-/**
- * Capability checks for seclvl.  The majority of the policy
- * enforcement for seclvl takes place here.
- */
-static int seclvl_capable(struct task_struct *tsk, int cap)
-{
-	int rc = 0;
-
-	/* init can do anything it wants */
-	if (tsk->pid == 1)
-		return 0;
-
-	if (seclvl > 0) {
-		rc = -EPERM;
-
-		if (cap == CAP_LINUX_IMMUTABLE)
-			seclvl_printk(1, KERN_WARNING, "Attempt to modify "
-				      "the IMMUTABLE and/or APPEND extended "
-				      "attribute on a file with the IMMUTABLE "
-				      "and/or APPEND extended attribute set "
-				      "denied in seclvl [%d]\n", seclvl);
-		else if (cap == CAP_SYS_RAWIO)
-			seclvl_printk(1, KERN_WARNING, "Attempt to perform "
-				      "raw I/O while in secure level [%d] "
-				      "denied\n", seclvl);
-		else if (cap == CAP_NET_ADMIN)
-			seclvl_printk(1, KERN_WARNING, "Attempt to perform "
-				      "network administrative task while "
-				      "in secure level [%d] denied\n", seclvl);
-		else if (cap == CAP_SETUID)
-			seclvl_printk(1, KERN_WARNING, "Attempt to setuid "
-				      "while in secure level [%d] denied\n",
-				      seclvl);
-		else if (cap == CAP_SETGID)
-			seclvl_printk(1, KERN_WARNING, "Attempt to setgid "
-				      "while in secure level [%d] denied\n",
-				      seclvl);
-		else if (cap == CAP_SYS_MODULE)
-			seclvl_printk(1, KERN_WARNING, "Attempt to perform "
-				      "a module operation while in secure "
-				      "level [%d] denied\n", seclvl);
-		else
-			rc = 0;
-	}
-
-	if (!rc) {
-		if (!(cap_is_fs_cap(cap) ? tsk->fsuid == 0 : tsk->euid == 0))
-			rc = -EPERM;
-	}
-
-	if (rc)
-		seclvl_printk(1, KERN_WARNING, "Capability denied\n");
-
-	return rc;
-}
-
-/**
- * Disallow reversing the clock in seclvl > 1
- */
-static int seclvl_settime(struct timespec *tv, struct timezone *tz)
-{
-	if (tv && seclvl > 1) {
-		struct timespec now;
-		now = current_kernel_time();
-		if (tv->tv_sec < now.tv_sec ||
-		    (tv->tv_sec == now.tv_sec && tv->tv_nsec < now.tv_nsec)) {
-			seclvl_printk(1, KERN_WARNING, "Attempt to decrement "
-				      "time in secure level %d denied: "
-				      "current->pid = [%d], "
-				      "current->group_leader->pid = [%d]\n",
-				      seclvl, current->pid,
-				      current->group_leader->pid);
-			return -EPERM;
-		}		/* if attempt to decrement time */
-	}			/* if seclvl > 1 */
-	return 0;
-}
-
-/* claim the blockdev to exclude mounters, release on file close */
-static int seclvl_bd_claim(struct inode *inode)
-{
-	int holder;
-	struct block_device *bdev = NULL;
-	dev_t dev = inode->i_rdev;
-	bdev = open_by_devnum(dev, FMODE_WRITE);
-	if (bdev) {
-		if (bd_claim(bdev, &holder)) {
-			blkdev_put(bdev);
-			return -EPERM;
-		}
-		/* claimed, mark it to release on close */
-		inode->i_security = current;
-	}
-	return 0;
-}
-
-/* release the blockdev if you claimed it */
-static void seclvl_bd_release(struct inode *inode)
-{
-	if (inode && S_ISBLK(inode->i_mode) && inode->i_security == current) {
-		struct block_device *bdev = inode->i_bdev;
-		if (bdev) {
-			bd_release(bdev);
-			blkdev_put(bdev);
-			inode->i_security = NULL;
-		}
-	}
-}
-
-/**
- * Security for writes to block devices is regulated by this seclvl
- * function.  Deny all writes to block devices in seclvl 2.  In
- * seclvl 1, we only deny writes to *mounted* block devices.
- */
-static int
-seclvl_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
-	if (current->pid != 1 && S_ISBLK(inode->i_mode) && (mask & MAY_WRITE)) {
-		switch (seclvl) {
-		case 2:
-			seclvl_printk(1, KERN_WARNING, "Write to block device "
-				      "denied in secure level [%d]\n", seclvl);
-			return -EPERM;
-		case 1:
-			if (seclvl_bd_claim(inode)) {
-				seclvl_printk(1, KERN_WARNING,
-					      "Write to mounted block device "
-					      "denied in secure level [%d]\n",
-					      seclvl);
-				return -EPERM;
-			}
-		}
-	}
-	return 0;
-}
-
-/**
- * The SUID and SGID bits cannot be set in seclvl >= 1
- */
-static int seclvl_inode_setattr(struct dentry *dentry, struct iattr *iattr)
-{
-	if (seclvl > 0) {
-		if (iattr->ia_valid & ATTR_MODE)
-			if (iattr->ia_mode & S_ISUID ||
-			    iattr->ia_mode & S_ISGID) {
-				seclvl_printk(1, KERN_WARNING, "Attempt to "
-					      "modify SUID or SGID bit "
-					      "denied in seclvl [%d]\n",
-					      seclvl);
-				return -EPERM;
-			}
-	}
-	return 0;
-}
-
-/* release busied block devices */
-static void seclvl_file_free_security(struct file *filp)
-{
-	struct dentry *dentry = filp->f_dentry;
-
-	if (dentry)
-		seclvl_bd_release(dentry->d_inode);
-}
-
-/**
- * Cannot unmount in secure level 2
- */
-static int seclvl_umount(struct vfsmount *mnt, int flags)
-{
-	if (current->pid != 1 && seclvl == 2) {
-		seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure "
-			      "level %d\n", seclvl);
-		return -EPERM;
-	}
-	return 0;
-}
-
-static struct security_operations seclvl_ops = {
-	.ptrace = seclvl_ptrace,
-	.capable = seclvl_capable,
-	.inode_permission = seclvl_inode_permission,
-	.inode_setattr = seclvl_inode_setattr,
-	.file_free_security = seclvl_file_free_security,
-	.settime = seclvl_settime,
-	.sb_umount = seclvl_umount,
-};
-
-/**
- * Process the password-related module parameters
- */
-static int processPassword(void)
-{
-	int rc = 0;
-	if (*passwd) {
-		char *p;
-
-		if (*sha1_passwd) {
-			seclvl_printk(0, KERN_ERR, "Error: Both "
-				      "passwd and sha1_passwd "
-				      "were set, but they are mutually "
-				      "exclusive.\n");
-			return -EINVAL;
-		}
-
-		p = kstrdup(passwd, GFP_KERNEL);
-		if (p == NULL)
-			return -ENOMEM;
-
-		if ((rc = plaintext_to_sha1(hashedPassword, p, strlen(p))))
-			seclvl_printk(0, KERN_ERR, "Error: SHA1 support not "
-				      "in kernel\n");
-
-		kfree (p);
-		/* All static data goes to the BSS, which zero's the
-		 * plaintext password out for us. */
-	} else if (*sha1_passwd) {	// Base 16
-		int i;
-		i = strlen(sha1_passwd);
-		if (i != (SHA1_DIGEST_SIZE * 2)) {
-			seclvl_printk(0, KERN_ERR, "Received [%d] bytes; "
-				      "expected [%d] for the hexadecimal "
-				      "representation of the SHA1 hash of "
-				      "the password.\n",
-				      i, (SHA1_DIGEST_SIZE * 2));
-			return -EINVAL;
-		}
-		while ((i -= 2) + 2) {
-			unsigned char tmp;
-			tmp = sha1_passwd[i + 2];
-			sha1_passwd[i + 2] = '\0';
-			hashedPassword[i / 2] = (unsigned char)
-			    simple_strtol(&sha1_passwd[i], NULL, 16);
-			sha1_passwd[i + 2] = tmp;
-		}
-	}
-	return rc;
-}
-
-/**
- * securityfs registrations
- */
-struct dentry *dir_ino, *seclvl_ino, *passwd_ino;
-
-static int seclvlfs_register(void)
-{
-	int rc = 0;
-
-	dir_ino = securityfs_create_dir("seclvl", NULL);
-
-	if (IS_ERR(dir_ino))
-		return PTR_ERR(dir_ino);
-
-	seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR,
-				dir_ino, &seclvl, &seclvl_file_ops);
-	if (IS_ERR(seclvl_ino)) {
-		rc = PTR_ERR(seclvl_ino);
-		goto out_deldir;
-	}
-	if (*passwd || *sha1_passwd) {
-		passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR,
-				dir_ino, NULL, &passwd_file_ops);
-		if (IS_ERR(passwd_ino)) {
-			rc = PTR_ERR(passwd_ino);
-			goto out_delf;
-		}
-	}
-	return rc;
-
-out_delf:
-	securityfs_remove(seclvl_ino);
-
-out_deldir:
-	securityfs_remove(dir_ino);
-
-	return rc;
-}
-
-static void seclvlfs_unregister(void)
-{
-	securityfs_remove(seclvl_ino);
-
-	if (*passwd || *sha1_passwd)
-		securityfs_remove(passwd_ino);
-
-	securityfs_remove(dir_ino);
-}
-
-/**
- * Initialize the seclvl module.
- */
-static int __init seclvl_init(void)
-{
-	int rc = 0;
-	static char once;
-
-	if (verbosity < 0 || verbosity > 1) {
-		printk(KERN_ERR "Error: bad verbosity [%d]; only 0 or 1 "
-		       "are valid values\n", verbosity);
-		rc = -EINVAL;
-		goto exit;
-	}
-	if (initlvl < -1 || initlvl > 2) {
-		seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "
-			      "[%d].\n", initlvl);
-		rc = -EINVAL;
-		goto exit;
-	}
-	seclvl = initlvl;
-	if ((rc = processPassword())) {
-		seclvl_printk(0, KERN_ERR, "Error processing the password "
-			      "module parameter(s): rc = [%d]\n", rc);
-		goto exit;
-	}
-
-	if ((rc = seclvlfs_register())) {
-		seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
-		goto exit;
-	}
-	/* register ourselves with the security framework */
-	if (register_security(&seclvl_ops)) {
-		seclvl_printk(0, KERN_ERR,
-			      "seclvl: Failure registering with the "
-			      "kernel.\n");
-		/* try registering with primary module */
-		rc = mod_reg_security(MY_NAME, &seclvl_ops);
-		if (rc) {
-			seclvl_printk(0, KERN_ERR, "seclvl: Failure "
-				      "registering with primary security "
-				      "module.\n");
-			seclvlfs_unregister();
-			goto exit;
-		}		/* if primary module registered */
-		secondary = 1;
-	}			/* if we registered ourselves with the security framework */
-
-	seclvl_printk(0, KERN_INFO, "seclvl: Successfully initialized.\n");
-
-	if (once) {
-		once = 1;
-		seclvl_printk(0, KERN_INFO, "seclvl is going away. It has been "
-				"buggy for ages. Also, be warned that "
-				"Securelevels are useless.");
-	}
- exit:
-	if (rc)
-		printk(KERN_ERR "seclvl: Error during initialization: rc = "
-		       "[%d]\n", rc);
-	return rc;
-}
-
-/**
- * Remove the seclvl module.
- */
-static void __exit seclvl_exit(void)
-{
-	seclvlfs_unregister();
-
-	if (secondary)
-		mod_unreg_security(MY_NAME, &seclvl_ops);
-	else if (unregister_security(&seclvl_ops))
-		seclvl_printk(0, KERN_INFO,
-			      "seclvl: Failure unregistering with the "
-			      "kernel\n");
-}
-
-module_init(seclvl_init);
-module_exit(seclvl_exit);
-
-MODULE_AUTHOR("Michael A. Halcrow <mike@halcrow.us>");
-MODULE_DESCRIPTION("LSM implementation of the BSD Secure Levels");
-MODULE_LICENSE("GPL");
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e4d81a4..cac0273 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -398,7 +398,7 @@
 		/* Standard string-based options. */
 		char *p, *options = data;
 
-		while ((p = strsep(&options, ",")) != NULL) {
+		while ((p = strsep(&options, "|")) != NULL) {
 			int token;
 			substring_t args[MAX_OPT_ARGS];
 
@@ -1923,18 +1923,40 @@
 	if (!*first) {
 		**to = ',';
 		*to += 1;
-	}
-	else
+	} else
 		*first = 0;
 	memcpy(*to, from, len);
 	*to += len;
 }
 
+static inline void take_selinux_option(char **to, char *from, int *first, 
+		                       int len)
+{
+	int current_size = 0;
+
+	if (!*first) {
+		**to = '|';
+		*to += 1;
+	}
+	else
+		*first = 0;
+
+	while (current_size < len) {
+		if (*from != '"') {
+			**to = *from;
+			*to += 1;
+		}
+		from += 1;
+		current_size += 1;
+	}
+}
+
 static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
 {
 	int fnosec, fsec, rc = 0;
 	char *in_save, *in_curr, *in_end;
 	char *sec_curr, *nosec_save, *nosec;
+	int open_quote = 0;
 
 	in_curr = orig;
 	sec_curr = copy;
@@ -1956,11 +1978,14 @@
 	in_save = in_end = orig;
 
 	do {
-		if (*in_end == ',' || *in_end == '\0') {
+		if (*in_end == '"')
+			open_quote = !open_quote;
+		if ((*in_end == ',' && open_quote == 0) ||
+				*in_end == '\0') {
 			int len = in_end - in_curr;
 
 			if (selinux_option(in_curr, len))
-				take_option(&sec_curr, in_curr, &fsec, len);
+				take_selinux_option(&sec_curr, in_curr, &fsec, len);
 			else
 				take_option(&nosec, in_curr, &fnosec, len);
 
diff --git a/sound/Makefile b/sound/Makefile
index 1f60797..5f6bef5 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -2,6 +2,7 @@
 #
 
 obj-$(CONFIG_SOUND) += soundcore.o
+obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/
@@ -11,4 +12,4 @@
   obj-y += last.o
 endif
 
-soundcore-objs  := sound_core.o sound_firmware.o
+soundcore-objs  := sound_core.o
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index c31b386..ff6e6fc 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -258,7 +258,7 @@
 
 static unsigned int rates[] = {8000, 11025, 16000, 22050};
 static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
-	.count	=  sizeof(rates) / sizeof(rates[0]),
+	.count	= ARRAY_SIZE(rates),
 	.list	= rates,
 	.mask	= 0,
 };
diff --git a/sound/oss/COPYING b/sound/oss/COPYING
deleted file mode 100644
index 916d1f0..0000000
--- a/sound/oss/COPYING
+++ /dev/null
@@ -1,339 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	Appendix: How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
-
-    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
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) 19yy name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index 5195bf9..3f81b79 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -96,7 +96,7 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 
-#include "cs46xxpm-24.h"
+#include "cs46xxpm.h"
 #include "cs46xx_wrapper-24.h"
 #include "cs461x.h"
 
@@ -389,8 +389,10 @@
 static int cs46xx_powerup(struct cs_card *card, unsigned int type);
 static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
 static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
+#ifdef CONFIG_PM
 static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
 static int cs46xx_resume_tbl(struct pci_dev *pcidev);
+#endif
 
 #if CSDEBUG
 
@@ -5389,8 +5391,10 @@
 	.id_table = cs46xx_pci_tbl,
 	.probe	  = cs46xx_probe,
 	.remove	  = __devexit_p(cs46xx_remove),
-	.suspend  = CS46XX_SUSPEND_TBL,
-	.resume	  = CS46XX_RESUME_TBL,
+#ifdef CONFIG_PM
+	.suspend  = cs46xx_suspend_tbl,
+	.resume	  = cs46xx_resume_tbl,
+#endif
 };
 
 static int __init cs46xx_init_module(void)
@@ -5420,7 +5424,7 @@
 module_init(cs46xx_init_module);
 module_exit(cs46xx_cleanup_module);
 
-#if CS46XX_ACPI_SUPPORT
+#ifdef CONFIG_PM
 static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
 {
 	struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
diff --git a/sound/oss/cs46xxpm-24.h b/sound/oss/cs46xxpm-24.h
deleted file mode 100644
index ad82db8..0000000
--- a/sound/oss/cs46xxpm-24.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
-*
-*      "cs46xxpm-24.h" --  Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
-*            -- tom woller (twoller@crystal.cirrus.com) or
-*               (pcaudio@crystal.cirrus.com).
-*
-*      This program is free software; you can redistribute it and/or modify
-*      it under the terms of the GNU General Public License as published by
-*      the Free Software Foundation; either version 2 of the License, or
-*      (at your option) any later version.
-*
-*      This program is distributed in the hope that it will be useful,
-*      but WITHOUT ANY WARRANTY; without even the implied warranty of
-*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*      GNU General Public License for more details.
-*
-*      You should have received a copy of the GNU General Public License
-*      along with this program; if not, write to the Free Software
-*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* 12/22/00 trw - new file. 
-*
-*******************************************************************************/
-#ifndef __CS46XXPM24_H
-#define __CS46XXPM24_H
-
-#include <linux/pm.h>
-#include "cs46xxpm.h"
-
-
-#define CS46XX_ACPI_SUPPORT 1
-#ifdef CS46XX_ACPI_SUPPORT
-/* 
-* for now (12/22/00) only enable the pm_register PM support.
-* allow these table entries to be null.
-*/
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
-static int cs46xx_resume_tbl(struct pci_dev *pcidev);
-#define CS46XX_SUSPEND_TBL cs46xx_suspend_tbl
-#define CS46XX_RESUME_TBL cs46xx_resume_tbl
-#else
-#define CS46XX_SUSPEND_TBL cs46xx_null
-#define CS46XX_RESUME_TBL cs46xx_null
-#endif
-
-#endif
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 2813e4c..d4844de 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -488,10 +488,6 @@
 static void ali_enable_special_channel(struct trident_state *stat);
 static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card);
 static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card);
-static void ali_restore_regs(struct trident_card *card);
-static void ali_save_regs(struct trident_card *card);
-static int trident_suspend(struct pci_dev *dev, pm_message_t unused);
-static int trident_resume(struct pci_dev *dev);
 static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel);
 static int ali_setup_multi_channels(struct trident_card *card, int chan_nums);
 static unsigned int ali_get_spdif_in_rate(struct trident_card *card);
@@ -507,13 +503,6 @@
 					       int chan_nums);
 static void ali_free_other_states_resources(struct trident_state *state);
 
-/* save registers for ALi Power Management */
-static struct ali_saved_registers {
-	unsigned long global_regs[ALI_GLOBAL_REGS];
-	unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
-	unsigned mixer_regs[ALI_MIXER_REGS];
-} ali_registers;
-
 #define seek_offset(dma_ptr, buffer, cnt, offset, copy_count)	do { \
         (dma_ptr) += (offset);	  \
 	(buffer) += (offset);	  \
@@ -3653,6 +3642,14 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+/* save registers for ALi Power Management */
+static struct ali_saved_registers {
+	unsigned long global_regs[ALI_GLOBAL_REGS];
+	unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
+	unsigned mixer_regs[ALI_MIXER_REGS];
+} ali_registers;
+
 static void
 ali_save_regs(struct trident_card *card)
 {
@@ -3746,6 +3743,7 @@
 	}
 	return 0;
 }
+#endif
 
 static struct trident_channel *
 ali_alloc_pcm_channel(struct trident_card *card)
@@ -4616,8 +4614,10 @@
 	.id_table = trident_pci_tbl,
 	.probe = trident_probe,
 	.remove = __devexit_p(trident_remove),
+#ifdef CONFIG_PM
 	.suspend = trident_suspend,
 	.resume = trident_resume
+#endif
 };
 
 static int __init
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 62d4d0c..0b0a016 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -551,10 +551,6 @@
 	return -ENODEV;
 }
 
-extern int mod_firmware_load(const char *, char **);
-EXPORT_SYMBOL(mod_firmware_load);
-
-
 MODULE_DESCRIPTION("Core sound module");
 MODULE_AUTHOR("Alan Cox");
 MODULE_LICENSE("GPL");
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c
index 6ddadfa..3a181d4 100644
--- a/sound/sound_firmware.c
+++ b/sound/sound_firmware.c
@@ -4,6 +4,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
+#include "oss/sound_firmware.h"
 
 static int do_mod_firmware_load(const char *fn, char **fp)
 {
@@ -59,8 +60,7 @@
  *	value zero on a failure.
  *
  *	Caution: This API is not recommended. Firmware should be loaded via
- *	an ioctl call and a setup application. This function may disappear
- *	in future.
+ *	request_firmware.
  */
  
 int mod_firmware_load(const char *fn, char **fp)
@@ -73,4 +73,6 @@
 	set_fs(fs);
 	return r;
 }
+EXPORT_SYMBOL(mod_firmware_load);
 
+MODULE_LICENSE("GPL");
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 8016541..5a97be6 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -2412,8 +2412,6 @@
 	CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
 };
 
-#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(struct snd_kcontrol_new))
-
 static int __init snd_dbri_mixer(struct snd_dbri * dbri)
 {
 	struct snd_card *card;
@@ -2424,7 +2422,7 @@
 	card = dbri->card;
 	strcpy(card->mixername, card->shortname);
 
-	for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
 		if ((err = snd_ctl_add(card,
 				snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
 			return err;
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 5105b6b..abe29da 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -181,9 +181,9 @@
 	case -ENODEV:
 		return -ENODEV;
 	/* errors that might occur during unplugging */
-	case -EPROTO:    /* EHCI */
-	case -ETIMEDOUT: /* OHCI */
-	case -EILSEQ:    /* UHCI */
+	case -EPROTO:
+	case -ETIME:
+	case -EILSEQ:
 		return -EIO;
 	default:
 		snd_printk(KERN_ERR "urb status %d\n", status);